AQS是java中並發的半壁江山,什么ReetrantLock、Condition、ReetrantReadWriteLock等,都是基於AQS實現。
一、AQS使用方式以及設計模式
AQS使用了模板模式,所謂的模板模式,通過一個例子來看-----以設計房子為例
1、模板抽象類:HouseTemplate
public abstract class HouseTemplate { protected HouseTemplate(String name){ this.name = name; } protected String name; protected abstract void buildDoor(); protected abstract void buildWindow(); protected abstract void buildWall(); protected abstract void buildBase(); //公共邏輯 public final void buildHouse(){ buildBase(); buildWall(); buildDoor(); buildWindow(); } }
2、子類1:HouseOne
public class HouseOne extends HouseTemplate { HouseOne(String name){ super(name); } @Override protected void buildDoor() { System.out.println(name +"的門要采用防盜門"); } @Override protected void buildWindow() { System.out.println(name + "的窗戶要面向北方"); } @Override protected void buildWall() { System.out.println(name + "的牆使用大理石建造"); } @Override protected void buildBase() { System.out.println(name + "的地基使用鋼鐵地基"); } }
3、子類2:HouseTwo
public class HouseTwo extends HouseTemplate { HouseTwo(String name){ super(name); } @Override protected void buildDoor() { System.out.println(name + "的門采用木門"); } @Override protected void buildWindow() { System.out.println(name + "的窗戶要向南"); } @Override protected void buildWall() { System.out.println(name + "的牆使用玻璃制造"); } @Override protected void buildBase() { System.out.println(name + "的地基使用花崗岩"); } }
4、測試類:Clienter
public class Clienter { public static void main(String[] args){ HouseTemplate houseOne = new HouseOne("房子1"); HouseTemplate houseTwo = new HouseTwo("房子2"); houseOne.buildHouse(); houseTwo.buildHouse(); } }
運行結果:
房子1的地基使用鋼鐵地基
房子1的牆使用大理石建造
房子1的門要采用防盜門
房子1的窗戶要面向北方
房子2的地基使用花崗岩
房子2的牆使用玻璃制造
房子2的門采用木門
房子2的窗戶要向南
房子1的地基使用鋼鐵地基
房子1的牆使用大理石建造
房子1的門要采用防盜門
房子1的窗戶要面向北方
房子2的地基使用花崗岩
房子2的牆使用玻璃制造
房子2的門采用木門
房子2的窗戶要向南
通過以上例子,我們認識了模板模式中的基本方法和模板方法,其中HouseTemplate中的buildHouse方法就是基本方法,其余四個均為模板方法。其中基本方法一般會用final修飾,保證其不會被子類修改,而模板方法則使用protected修飾,表明其需要在子類中實現。
AQS也是基於這種模式來實現的,所以如果你要自己實現一個鎖,就需要針對性的覆蓋與實現AQS的某些方法。當然AQS這么強大,提供了獨占式鎖以及共享式鎖的功能,你需要根據獨占還是共享來選擇實現哪些方法。
獨占式:
1、獲取
tryAcquire
accquire
acquireInterruptibly
tryAcquireNanos
2、釋放
tryRelease
release
共享式:
1、獲取
tryAcquireShared
acquireShared
acquireSharedInterruptibly
tryAcquireSharedNanos
2、釋放
tryReleaseShared
releaseShared
獨占式、共享式都要實現的方法
1、這個同步器是否處於獨占模式 isHeldExclusively
2、同步狀態state:
getState:獲取當前的同步狀態
setState:設置當前同步狀態
compareAndSetState 使用CAS設置狀態,保證狀態設置的原子性
二、基於AQS自實現的鎖(獨占式)
package com.xiangxue.ch4.aqs; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** *類說明:實現一個自己的類ReentrantLock */ public class SelfLock implements Lock{ //state 表示獲取到鎖 state=1 獲取到了鎖,state=0,表示這個鎖當前沒有線程拿到 private static class Sync extends AbstractQueuedSynchronizer{ //是否占用 protected boolean isHeldExclusively() { return getState()==1; } //通過state維護當前是否有線程拿到鎖,獲取鎖也就是通過CAS的方式將state從0設置為1,成功后將獨占鎖設置為自己 protected boolean tryAcquire(int arg) { if(compareAndSetState(0,1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } //這地方不用使用CAS的原因是釋放鎖只有當前拿到鎖的一個線程可以釋放,所以不存在競爭條件 protected boolean tryRelease(int arg) { if(getState()==0) { throw new UnsupportedOperationException(); } setExclusiveOwnerThread(null); setState(0); return true; } Condition newCondition() { return new ConditionObject(); } } private final Sync sycn = new Sync(); @Override public void lock() { sycn.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sycn.acquireInterruptibly(1); } @Override public boolean tryLock() { return sycn.tryAcquire(1); } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sycn.tryAcquireNanos(1, unit.toNanos(time)); } @Override public void unlock() { sycn.release(1); } @Override public Condition newCondition() { return sycn.newCondition(); } }
三、基於AQS自實現的鎖(共享式)
package com.xiangxue.ch4.aqs; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject; /** *類說明:自定義共享鎖 */ public class TrinityLock { //為3表示允許兩個線程同時獲得鎖 private final Sync sync = new Sync(3); private static final class Sync extends AbstractQueuedSynchronizer { Sync(int count) { if (count <= 0) { throw new IllegalArgumentException("count must large than zero."); } setState(count); } public int tryAcquireShared(int reduceCount) { for (;;) { int current = getState(); int newCount = current - reduceCount; if (newCount < 0 || compareAndSetState(current, newCount)) { return newCount; } } } public boolean tryReleaseShared(int returnCount) { for (;;) { int current = getState(); int newCount = current + returnCount; if (compareAndSetState(current, newCount)) { return true; } } } final ConditionObject newCondition() { return new ConditionObject(); } } public void lock() { sync.acquireShared(1); } public void unlock() { sync.releaseShared(1); } public void lockInterruptibly() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public boolean tryLock() { return sync.tryAcquireShared(1) >= 0; } public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(time)); } public Condition newCondition() { return sync.newCondition(); } }
簡單來說,就是將state初始化>1,表示一共可以有多個線程占有,不過這種沒有實現讀跟寫的分離。