java-基於AQS實現鎖
阿新 • • 發佈:2021-06-25
java-基於AQS實現鎖
AQS
是AbstractQueuedSynchronizer 抽象佇列同步器
1.採用雙向連結串列的資料結構,當多執行緒同時競爭鎖的時候,第一個執行緒拿到鎖後,後續的執行緒封裝成Node節點依次進入同步佇列進行排隊等待。
2.AQS內部會採取自旋(死迴圈)的機制,一直判斷頭節點是否滿足獲取鎖的條件,當鎖被第一個執行緒釋放後,佇列中頭節點條件滿足(檢查鎖的狀態是否為0),然後讓頭節點獲取到鎖,並脫離佇列,如下圖:
package me.ele.checkcenter.marketing.util.Test; import org.jetbrains.annotations.NotNull; import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** * @author: 謝洪偉 * 2021/6/25 11:40 上午 */ public class MyLock implements Lock { private Sync sync = new Sync(); private static class Sync extends AbstractQueuedSynchronizer{ protected Sync() { super(); } @Override protected boolean tryAcquire(int arg) { // cas比較記憶體中原始值0,則修改為傳入的值 if (compareAndSetState(0, arg)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int arg) { if (getState() == 0) { throw new UnsupportedOperationException(); } setExclusiveOwnerThread(null); setState(0); return true; } @Override protected int tryAcquireShared(int arg) { return super.tryAcquireShared(arg); } @Override protected boolean tryReleaseShared(int arg) { return super.tryReleaseShared(arg); } /** * 是否同步獨佔 true 已被獨佔 false 未被獨佔 * @return */ @Override protected boolean isHeldExclusively() { return getState() == 1; } Condition newCondition() { return new ConditionObject();//AQS已經實現condition } } @Override public void lock() { sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override public boolean tryLock() { return sync.tryAcquire(1); } @Override public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1,unit.toNanos(time)); } @Override public void unlock() { sync.release(1); } @NotNull @Override public Condition newCondition() { return sync.newCondition(); } public static void main(String[] args) { MyLock lock = new MyLock(); for (int i = 0; i < 10; i++) { new Thread(()->{ lock.lock(); try { Thread.sleep(1000); } catch (InterruptedException e) { } System.out.println("time="+new Date()); lock.unlock(); }).start(); } } }