AbstractQueueSynchronizer 是 jdk 自帶的一個 構建 鎖 和 同步器的基類。他內部使用 CAS (compareAndSet)保證隊列的原子性, 同時利用 FIFO 隊列實現 線程間的競爭.將基礎的同步細節放在抽象類裏面。想 countDownLatch,semaphore,CyclicBarrier ,reentrantLock都是依賴 aqs 實現的。
實現代碼
public class SelfSynchronizedAqs {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
int state = getState();
if (state == 0) {
System.out.println("arg = 狀態錯誤");
return false;
}
setState(0);
setExclusiveOwnerThread(null);
return true;
}
}
Sync sync = new Sync();
public void lock(){
sync.acquire(1);
}
public void unLock(){
sync.release(1);
}
}
具體測試代碼
/**
* @author yueye
* @date 2020/3/9 17:40
* @desc
*/
public class TestSelfAqsByCountLatch {
static int a = 0 ;
/**
* 比線程數量多一個原因是 務必保證 所有的線程全部執行完(a++) 操作,而且只執行一次
*
*/
static int num = 31;
// private static CyclicBarrier barrier = new CyclicBarrier(31);
private static CountDownLatch barrier = new CountDownLatch(num);
private static SelfSynchronizedAqs selfSynchronizedAqs = new SelfSynchronizedAqs();
public static void main(String[] args) throws Exception {
for (int i = 0; i < 30; i++) {
Thread thread = new Thread((() -> {
for (int j = 0; j < 10000; j++) {
increment();
}
try {
barrier.countDown();
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}));
thread.start();
}
barrier.countDown();
barrier.await();
barrier = new CountDownLatch(num);
// 等待一會 防止 創建線程過快
System.out.println(System.currentTimeMillis() + "aaaaaaaaaaaaaaaaaaaaaaaaa= " + a);
a = 0;
int w = 0;
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> {
for (int j = 0; j < 10000; j++) {
increment2();
}
try {
barrier.countDown();
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
w ++;
thread.start();
}
barrier.countDown();
barrier.await();//等30個線程累加完畢
System.out.println(System.currentTimeMillis() + "bbbbbbbbbbbbbbbbbbbb = " + a);
}
private static void increment2() {
selfSynchronizedAqs.lock();
a++;
selfSynchronizedAqs.unLock();
}
private static void increment() {
a++;
}
}
輸出結果
1583749759633aaaaaaaaaaaaaaaaaaaaaaaaa= 292263
1583749759686bbbbbbbbbbbbbbbbbbbb = 300000