1. 程式人生 > 其它 >java-基於AQS實現鎖

java-基於AQS實現鎖

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();
        }
    }
}