• AQS原理


    1 概述

    AQS 是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架

    特点:

    • 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取 锁和释放锁
      • getState - 获取 state 状态
      • setState - 设置 state 状态
      • compareAndSetState - cas 机制设置 state 状态
      • 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
    • 提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList
    • 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet

    子类主要实现一些常见方法如:

    • tryAcquire
    • tryRelease
    • tryAcquireShared
    • tryReleaseShared
    • isHeldExclusively

    默认抛出 UnsupportedOperationException

    获取锁的案例

    // 如果获取锁失败
    if (!tryAcquire(arg)) {
     // 入队, 可以选择阻塞当前线程 park unpark
    }
    
    • 1
    • 2
    • 3
    • 4

    释放锁的案例

    // 如果释放锁成功
    if (tryRelease(arg)) {
     // 让阻塞线程恢复运行
    }
    
    • 1
    • 2
    • 3
    • 4

    2 自定义不可重入锁

    自定义同步器

    final class MySync extends AbstractQueuedSynchronizer {
        
         @Override
         protected boolean tryAcquire(int acquires) {
             if (acquires == 1){
                 if (compareAndSetState(0, 1)) {
                     setExclusiveOwnerThread(Thread.currentThread());
                     return true;
                 }
             }
             return false;
         }
         @Override
         protected boolean tryRelease(int acquires) {
             if(acquires == 1) {
                 if(getState() == 0) {
                     throw new IllegalMonitorStateException();
                 }
                 setExclusiveOwnerThread(null);
                 setState(0);
                 return true;
             }
             return false;
         }
         protected Condition newCondition() {
             return new ConditionObject();
         }
         @Override
         protected boolean isHeldExclusively() {
             return getState() == 1;
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    自定义锁

    class MyLock implements Lock {
         static MySync sync = new MySync();
        
         @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();
         }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    测试

    MyLock lock = new MyLock();
    new Thread(() -> {
         lock.lock();
         try {
             log.debug("locking...");
             sleep(1);
         } finally {
             log.debug("unlocking...");
             lock.unlock();
         }
    },"t1").start();
    
    new Thread(() -> {
         lock.lock();
         try {
             log.debug("locking...");
         } finally {
             log.debug("unlocking...");
             lock.unlock();
         }
    },"t2").start();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果:

    c.TestAqs [t1] - locking... 
    c.TestAqs [t1] - unlocking... 
    c.TestAqs [t2] - locking... 
    c.TestAqs [t2] - unlocking...
    
    • 1
    • 2
    • 3
    • 4

    不可重入测试

    MyLock lock = new MyLock();
    new Thread(() -> {
        lock.lock();
        log.debug("locking...");
        lock.lock();
        log.debug("locking...");
         try {
             log.debug("locking...");
             sleep(1);
         } finally {
             log.debug("unlocking...");
             lock.unlock();
         }
    },"t1").start();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果:

    c.TestAqs [t1] - locking... 
    
    • 1

    该线程陷入死锁, 说明lock锁为不可重入锁.

  • 相关阅读:
    【Java笔记+踩坑】设计模式——原型模式
    Spring源码:SpringBean 的注册-XML源码解析
    数据仓库与数据挖掘的第二章课后习题
    搭建灾情快速分析系统 | Bigemap助力防灾减灾重点工作
    Python 中的方法重载
    什么是JSF AV C++编码规范?
    《洛谷深入浅出基础篇》——P3405 citis and state ——哈希表
    etcd中version,revision,mod_revision,create_revision的区别
    OpenCV 图像与视频的基础操作
    【机器学习9】前馈神经网络
  • 原文地址:https://blog.csdn.net/ABestRookie/article/details/126353457