public class SynchronizedTest { // 實例方法,方法訪問標誌ACC_SYNCHRONIZED,鎖對象是對象實例 public synchronized void test1(){} // 靜態方法,方法訪問標誌ACC_SYNCHRONIZED,鎖對象是MetaSpace中的Class // 至關於類的全局鎖,會鎖住全部調用該方法的線程 public synchronized static void test2(){} public void test3() { //同步代碼塊,在代碼塊前增長monitorenter指令,代碼塊後增長monitorexit指令 SynchronizedTest synchronizedTest = new SynchronizedTest(); synchronized (synchronizedTest) {} // 類鎖,效果等同於鎖靜態方法。代碼塊先後增長monitorenter、monitorexit指令 synchronized (SynchronizedTest.class) {} } }
可jclasslib查看Acc_SYNCHRONIZED標誌和monitorenter、monitorexit指令html
test1 方法:java
Access flags: 0x0021[public synchronized]
test2 方法:node
Access flags: 0x0029[public static synchronized]
test3方法Code操做碼:c#
0 new #2 <com/java/study/jvm/SynchronizedTest> 3 dup 4 invokespecial #3 <com/java/study/jvm/SynchronizedTest.<init>> 7 astore_1 8 aload_1 9 dup 10 astore_2 11 monitorenter 12 aload_2 13 monitorexit 14 goto 22 (+8) 17 astore_3 18 aload_2 19 monitorexit 20 aload_3 21 athrow 22 ldc #2 <com/java/study/jvm/SynchronizedTest> 24 dup 25 astore_2 26 monitorenter 27 aload_2 28 monitorexit 29 goto 39 (+10) 32 astore 4 34 aload_2 35 monitorexit 36 aload 4 38 athrow 39 return
核心組件併發
圖示過程:jvm
解釋:函數
ReentrantLock初始化時,會new一個同步類(默認非公平NonfairSync,當傳入公平參數fair=true時,則new公平類FairSync);而FairSync 和NonfairSync都繼承ReentrantLock中內部類Sync,Sync則繼承同步器AbstractQueuedSynchronizer。UML圖以下(http://www.javashuo.com/article/p-ahbodinp-ny.html 截取):性能
public class ReentrantLock implements Lock, java.io.Serializable { abstract static class Sync extends AbstractQueuedSynchronizer { final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //第2次嘗試獲取鎖 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } static final class NonfairSync extends Sync { final void lock() { // 可不進入隊列,直接搶鎖 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } }
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { public final void acquire(int arg) { // 步驟3,加入等待隊列,默認排他鎖 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
而繼續addWaiter、enq和acquireQueued則是實現如下圖示過程:
優化
private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } //前置節點爲null的臨界條件,第一個線程進入等待隊列 enq(node); return node; }
前置節點爲null的臨界條件,第一個線程進入等待隊列,進行初始化ui
private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize //隊列初始化 if (compareAndSetHead(new Node())) tail = head; } else { //雙向鏈表添加元素 node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
node屬性值介紹:
對應源碼:
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable { static final class Node { static final Node EXCLUSIVE = null; static final int CANCELLED = 1; static final int SIGNAL = -1; static final int CONDITION = -2; static final int PROPAGATE = -3; volatile int waitStatus; volatile Node prev; volatile Node next; volatile Thread thread; Node nextWaiter; final boolean isShared() { return nextWaiter == SHARED; } final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial head or SHARED marker } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } } }
重入鎖的可重複進入在如下代碼中實現(非公平鎖示例,公平鎖代碼同樣):
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { ... } // c > 0 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
第一處不公平地方(lock方法):
static final class NonfairSync extends Sync { final void lock() { // 可不進入隊列,直接搶鎖 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } }
static final class FairSync extends Sync { final void lock() { acquire(1); } }
第二處不公平的地方(tryAcquire):
static final class NonfairSync extends Sync { protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
abstract static class Sync extends AbstractQueuedSynchronizer { final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //發現鎖被釋放時,可直接搶鎖 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } ... } }
公平鎖
static final class FairSync extends Sync { protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 必須同步器中隊列沒有線程在等待,纔去獲取鎖 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } ... } }
第三處不公平地方,加入隊列時,前置節點是頭節點:
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { ... } } }