1. 程式人生 > 實用技巧 >通過AQS實現自定義鎖

通過AQS實現自定義鎖

一、前提知識
通過AQS實現自定義鎖,目前僅實現了lock和unlock , 如果你讀過AQS原始碼,以ReentrantLock為例:(abstract static class Sync extends AbstractQueuedSynchronizer)(static final class FairSync extends Sync),
例如ReentrantLock、CountDownLatch、Semaphore等 都是自己對抽象類AbstractQueuedSynchronizer進行了自己的實現,AQS的核心是CAS+volatile,這裡所謂的CAS是因為在多執行緒的情況下,沒有使用synchronized來同步而是使用了
大量的CAS操作(例如執行緒節點獲取鎖和加到尾節點上都使用了CAS操作),內部還維護了一個雙向連結串列有頭節點和尾節點,定義了一個private volatile int state 具體的含義由子類自己決定,ReentrantLock中state的含義是:當state
等於0時證明當前鎖沒有任何的執行緒佔有,state=1時,證明有執行緒佔有這把鎖,記住這裡因為ReentrantLock具有可重入性,所以重入一次state加一,當state減少至0時,釋放鎖。

二、具體的實現

1、自定義鎖 這裡僅僅實現了lock和unlock。

package com.dongliang.juc.c_021_02_AQS;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author D-L
 * @description: 通過AQS實現自定義鎖,目前僅實現了lock和unlock
 * @date 2020-11-22 13:59:18
 
*/ public class MyLock implements Lock, java.io.Serializable{ private static final long serialVersionUID = 7373984872572414699L; private static final class MySync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; @Override
protected boolean tryAcquire(int arg) { if(compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int arg) { setExclusiveOwnerThread(null); setState(0); return true; } @Override protected boolean isHeldExclusively() { return getState() == 1; } } private MySync sync = new MySync(); @Override public void lock() { sync.acquire(1); } @Override public void unlock() { sync.release(1); } @Override public void lockInterruptibly() throws InterruptedException { } @Override public boolean tryLock() { return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; } @Override public Condition newCondition() { return null; } }

2、測試方法:通過多執行緒對int值進行操作。

package com.dongliang.juc.c_021_02_AQS;

import java.util.concurrent.locks.Lock;

/**
 * @author D-L
 * @description: 對自定義鎖測試
 * @date 2020-11-22 14:10:18
 */
public class MyLockTest {
    public static int m = 0;
    public static Lock lock = new MyLock();

    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[100];

        for(int i=0; i<threads.length; i++) {
            threads[i] = new Thread(()->{
                try {
                    //執行lock方法
                    lock.lock();
                    for (int j = 0; j < 100; j++) m++;
                } finally {
                    //出現異常需要手動釋放鎖
                    lock.unlock();
                }
            });
        }
        //啟動執行緒
        for(Thread t : threads) t.start();

        for (Thread t : threads) t.join();
        System.out.println(m);
    }
}