基於AQS實現不可重入的獨佔鎖;


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

/**
 * @ClassName NonReentrantLock
 * @Author laixiaoxing
 * @Date 2019/8/13 下午11:26
 * @Description 可重入鎖, 每次進入一次state就加1 出去一次就減1
 * 不可重入鎖,定義state爲1表示鎖已經被某個線程獲取了, 0表示鎖還在 不需要記錄獲取鎖的次數
 * <p>
 * 這個是個不可重入鎖,且支持條件變量
 * @Version 1.0
 */
public class NonReentrantLock implements Lock {

    private final Sync sync = new Sync();

    @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, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }


    /**
     * 輔助內部類
     * 繼承AQS 重寫一些方法實現自己想要的功能
     * 1.獲取鎖狀態 通過state
     * 2.嘗試獲取鎖 設置state爲1
     * 3.嘗試釋放鎖 設置state爲0
     * 4.提供條件變量接口
     */
    private static class Sync extends AbstractQueuedSynchronizer {


        /**
         * 是否鎖已經被持有
         *
         * @return
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }


        /**
         * 嘗試獲取鎖
         *
         * @param acquires
         * @return
         */
        @Override
        public boolean tryAcquire(int acquires) {
            //如果state爲0 設置爲1 成功
            if (compareAndSetState(0, 1)) {
                //設置獨佔模式的擁有者
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            } else {
                return false;
            }
        }

        @Override
        protected boolean tryRelease(int releases) {
            if (getState() == 0) {
                throw new IllegalMonitorStateException();
            }
            //清空獨佔模式的擁有者
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        /**
         * 提供條件變量接口
         *
         * @return
         */
        Condition newCondition() {
            return new ConditionObject();
        }

    }


    /**
     * 使用這個鎖實現生產者消費者模型
     *
     * @param args
     */
    public static void main(String[] args) {
        NonReentrantLock reentrantLock = new NonReentrantLock();
        Condition full = reentrantLock.newCondition();
        Condition empty = reentrantLock.newCondition();
        int size = 5;
        Queue queue = new LinkedBlockingQueue(size);


        Thread producer = new Thread(() -> {

            while (true) {
                reentrantLock.lock();
                //滿了
                if (queue.size() == size) {
                    //阻塞
                    try {
                        full.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    queue.add("a");
                    empty.signal();
                }

                reentrantLock.unlock();
            }
        });


        Thread comsumer = new Thread(() -> {
            while (true) {
                reentrantLock.lock();
                //不空
                if (queue.size() != 0) {
                    String a = (String) queue.poll();
                    System.out.println("消費者消費" + a);
                    full.signal();
                } else {
                    try {
                        empty.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                reentrantLock.unlock();
            }
        });


        producer.start();
        comsumer.start();

    }
}

原理:AQS是一個抽象類,裏面定義了一個state變量和一個隊列,隊列元素爲用線程對象封裝成的Node, 同時還有一個內部類conditionObject, conditionObject內有一個條件隊列,元素和AQS的裏面的Node類似。

這裏定義了state爲1時鎖被拿走,0時無鎖。 當通過cas獲取鎖失敗的時候,會將這個線程封裝成node放到AQS內的等待隊列裏面去,同時使用park方法掛起這個線程。
如果獲取鎖成功,會將state更新爲1。
當釋放鎖的時候,將state更新爲0,同時去阻塞隊列裏面喚醒頭節點下一個節點的Node裏面的線程,讓它競爭鎖。

調用condition的await方法時,將state更新爲0,且將該線程封裝成node放到condition的條件隊列裏面,然後掛起。
調用condition的sign方法時,將線程從條件隊列移到AQS的阻塞隊列裏面,然後喚醒這個線程,讓這個線程能夠參與競爭鎖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章