Java并发-AQS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22271479/article/details/85019245

同步器 AbstractQueuedSynchronizer(AQS)

理解

同步器维护了一个同步队列(双向链表),指定了基础的同步策略
支持 独占 和 共享两种模式
运用了大量的CAS和自旋操作
AQS做了在获取不到锁的时候,入队操作 以及出队和唤醒操作

AQS 实际上市没有锁的,是通过将线程装入同步队列中,通过自旋即“死循环”的操作来阻塞线程,通过CAS来实现线程状态的原子性切换切换

提供扩展实现的方法

//独占模式必须重写的方法
protected boolean tryAcquire(int arg);
protected boolean tryRelease(int arg);
//共享模式必须重写的方法
protected int tryAcquireShared(int arg);
protected boolean tryReleaseShared(int arg);
//是否是独占模式,这里是Condition需要用到的,condition相当于一个资源协调器,实现wait和notify的功能
protected boolean isHeldExclusively();

示例

这里要实现,该锁只能同时被两个线程访问,其余的线程都将进入同步队列。

/**
 * describe:
 * E-mail:[email protected]  date:2018/12/15
 *
 * @Since 0.0.1
 */
public class TwoLockAllow implements Lock {

    private final static Sync sync = new Sync(2);

    /**
     * 实现做多两个线程共享资源
     * lock和unlock操作都是阻塞的
     */
    private static class Sync extends AbstractQueuedSynchronizer {

        Sync(int count) {
            if (count <= 0) {
                throw new IllegalArgumentException("count must large 0");
            }
            setState(count);
        }

        /**
         * compareAndSwapInt java通过调用c代码来操作内存,原子操作去更改该值
         *
         * 获取资源,<0 进入队列中等待
         * compareAndSetState()
         * compareAndSwapInt(Object var1, long var2, int var4, int var5)
         * var1 : 修改的字段锁处于的对象
         * var2 : stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
         *       int值得偏移量
         * var4 : 当前值也是期望值
         * var5 : 更新后的值
         *
         * ===================实现逻辑=========================
         * public final void acquireShared(int arg) {
         *   if (tryAcquireShared(arg) < 0)
         *      doAcquireShared(arg);
         * }
         * 我们可以看出来,当tryAcquireShared的返回值小于0的时候,将会将该线程入队操作。
         * 这里是共享锁,我们通过重写tryAcquireShared方法,来控制获取锁的规则。
         *
         * 当当前状态锁的state小于0的时候,后续的线程将入队,否则直接得到锁资源。
         *
         * 后面的获取锁操作都会调用用户定义的tryAcquireShared方法
         * @param arg
         * @return
         */
        @Override
        protected int tryAcquireShared(int arg) {
            for (;;){
                int currentCount = getState();
                int newCount = currentCount - arg;
                if (newCount < 0 || compareAndSetState(currentCount,newCount)){
                    return newCount;
                }
            }

        }

        /**
         * 这里是释放资源,更改state的状态
         * @param arg
         * @return
         */
        @Override
        protected boolean tryReleaseShared(int arg) {

            for (;;){
                int currentCount = getState();
                int newCount = currentCount + arg;
                if (compareAndSetState(currentCount,newCount)){
                    return true;
                }
            }
        }
    }

    @Override
    public void lock() {
        sync.acquireShared(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 void unlock() {
        sync.releaseShared(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }

}

class test {
    public static final Lock lock = new TwoLockAllow();

    static class T extends Thread {
        @Override
        public void run() {
            lock.lock();
            System.out.println("==" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            T t = new T();
            t.start();
        }
    }
}

GitHub主页

猜你喜欢

转载自blog.csdn.net/qq_22271479/article/details/85019245