AQS,即AbstractQueuedSynchronizer, 隊列同步器,它是多線程訪問共享資源的同步器框架,Java中的ReentrantLock/Semaphore/CountDownLatch等同步組件都依賴於它。它維護了一個同步器狀態 (volatile int state 代表共享資源)和一個線程等待隊列(多線程爭用資源被阻塞時會進入此雙向隊列 ,FIFO )
AQS大致流程,以ReentrantLock為例
這篇講的比較清楚 https://www.cnblogs.com/fanBlog/p/9336126.html
ReentrantLock 中的公平鎖和非公平鎖
公平鎖能保證:老的線程排隊使用鎖,新線程仍然排隊使用鎖。
非公平鎖保證:老的線程排隊使用鎖;但是可能會出現新線程要先於等待隊列中的線程搶占到鎖
公平鎖的實現是每次獲取鎖的時候會判斷等待隊列中是否還有線程在等待,而非公平鎖就不會判斷等待隊列中是否還有線程在等待,新來的線程有可能比等待中的線程先搶到鎖
公平鎖獲取鎖的方法
/** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // !hasQueuedPredecessors()保證了不論是新的線程還是已經排隊的線程都順序使用鎖 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
非公平鎖獲取鎖的方法
/** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 新的線程可能搶占已經排隊的線程的鎖的使用權 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; }
什么是CAS
在並發環境下,某個線程對共享變量先進行操作,如果沒有其他線程爭用共享數據那操作就成功;如果存在數據的爭用沖突,那就才去補償措施,比如不斷的重試機制,直到成功為止,因為這種樂觀的並發策略不需要把線程掛起,效率要比采用鎖的機制高。在硬件指令集的發展驅動下,使得 "操作和沖突檢測" 這種看起來需要多次操作的行為只需要一條處理器指令便可以完成,這些指令中就包括非常著名的CAS指令(Compare-And-Swap比較並交換)
public final int incrementAndGet(){ for(;;){ int current=get(); int next=current+1; if(compareAndSet(current,next)){ return next; } } }