标签:导致 效率 rsync ror rip cas 异常 阻塞 origin
Java中的每个对象都可以作为锁。
一般锁有4种状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态。
在进一步深入之前,我们先认识下两个概念:对象头和monitor。
什么是对象头?
在hotspot虚拟机中,对象在内存的分布分为3个部分:对象头,实例数据,和对齐填充。
mark word被分成两部分,lock word和标志位。
Klass ptr指向Class字节码在虚拟机内部的对象表示的地址。
Fields表示连续的对象实例字段。
mark word 被设计为非固定的数据结构,以便在极小的空间内存储更多的信息。比如:在32位的hotspot虚拟机中:
如果对象处于未被锁定的情况下。mark word 的32bit空间中有25bit存储对象的哈希码、4bit存储对象的分代年龄、2bit存储锁的标记位、1bit固定为0。而在其他的状态下(轻量级锁、重量级锁、GC标记、可偏向)下对象的存储结构为
monitor是线程私有的数据结构,每一个线程都有一个可用monitor列表(栈?),同时还有一个全局的可用列表,先来看monitor的内部
monitor的作用:在 java 虚拟机中,线程一旦进入到被synchronized修饰的方法或代码块时,指定的锁对象通过某些操作将对象头中的LockWord指向monitor的起始地址与之关联,同时monitor中的Owner存放拥有该锁的线程的唯一标识,确保一次只能有一个线程执行该部分的代码,线程在获取锁之前不允许执行该部分的代码。
下述代码中,当线程访问同步方法method1时,会在对象头(SynchronizedTest.class对象的对象头)和栈帧的锁记录中存储锁偏向的线程ID,下次该线程在进入method2,只需要判断对象头存储的线程ID是否为当前线程,而不需要进行CAS操作进行加锁和解锁(因为CAS原子指令虽然相对于重量级锁来说开销比较小但还是存在非常可观的本地延迟)。
Compare And Swap:CAS 指的是现代 CPU 广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。这个指令会对内存中的共享数据做原子的读写操作。简单来说,CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”。它们虽然看似复杂,但却是 Java 5 并发机制优于原有锁机制的根本。(这段描述引自《Java并发编程实践》)。简单的来说,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则返回V。这是一种乐观锁的思路,它相信在它修改之前,没有其它线程去修改它;而Synchronized是一种悲观锁,它认为在它修改之前,一定会有其它线程去修改它,悲观锁效率很低。
1 public class SynchronizedTest { 2 private static Object lock = new Object(); 3 public static void main(String[] args) { 4 method1(); 5 method2(); 6 } 7 synchronized static void method1() {} 8 synchronized static void method2() {} 9 }
利用了CPU原语Compare-And-Swap。
线程可以通过两种方式锁住一个对象:
获取锁(monitorenter)的大概过程:
释放锁(monitorexit)的大概过程:
当锁处于这个状态下,其他线程试图获取锁都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程。
先来看一下ReentrantLock的源码:
1 public class ReentrantLock implements Lock, java.io.Serializable { 2 private final Sync sync; 3 abstract static class Sync extends AbstractQueuedSynchronizer { 4 5 /** 6 * Performs {@link Lock#lock}. The main reason for subclassing 7 * is to allow fast path for nonfair version. 8 */ 9 abstract void lock(); 10 11 /** 12 * Performs non-fair tryLock. tryAcquire is implemented in 13 * subclasses, but both need nonfair try for trylock method. 14 */ 15 final boolean nonfairTryAcquire(int acquires) { 16 final Thread current = Thread.currentThread(); 17 int c = getState(); 18 if (c == 0) { 19 if (compareAndSetState(0, acquires)) { 20 setExclusiveOwnerThread(current); 21 return true; 22 } 23 } 24 else if (current == getExclusiveOwnerThread()) { 25 int nextc = c + acquires; 26 if (nextc < 0) // overflow 27 throw new Error("Maximum lock count exceeded"); 28 setState(nextc); 29 return true; 30 } 31 return false; 32 } 33 34 protected final boolean tryRelease(int releases) { 35 int c = getState() - releases; 36 if (Thread.currentThread() != getExclusiveOwnerThread()) 37 throw new IllegalMonitorStateException(); 38 boolean free = false; 39 if (c == 0) { 40 free = true; 41 setExclusiveOwnerThread(null); 42 } 43 setState(c); 44 return free; 45 } 46 47 } 48 //默认非公平锁 49 public ReentrantLock() { 50 sync = new NonfairSync(); 51 } 52 //fair为false时,采用公平锁策略 53 public ReentrantLock(boolean fair) { 54 sync = fair ? new FairSync() : new NonfairSync(); 55 } 56 public void lock() { 57 sync.lock(); 58 } 59 public void unlock() { sync.release(1);} 60 public Condition newCondition() { 61 return sync.newCondition(); 62 } 63 ... 64 }
标签:导致 效率 rsync ror rip cas 异常 阻塞 origin
原文地址:http://www.cnblogs.com/jjfan0327/p/6852994.html