AQS总结

在这里插入图片描述

概述

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

特点:

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

子类主要实现这样一些方法(默认抛出UnsupportedOperationException

  • tryAcquire
  • tryRelease
  • tryAcquireShared
  • tryReleaseShared
  • isHeldExclusively

主要用到 AQS 的并发工具类

在这里插入图片描述

ReentrantLock 原理

非公平锁实现原理

  1. 尝试着使用CAS操作将锁的状态state由0修改为1,修改成功则线程获得锁。

  2. 不成功就会再次尝试去抢锁,以及判断这个线程是否是当前持有锁的线程(如果是只需要将state+1,代表锁重入)。

  3. 抢锁没成功,也不是持有锁的线程,那么就会添加到等待队列然后调用LockSupport.park()方法进行阻塞等待,然后被唤醒。

公平锁加锁过程

  1. 如果当前锁没有被其他线程持有,并且等待队列中也没有其他线程等待,那么就使用CAS操作去抢锁。

  2. 或者线程就是当前持有锁的线程,那么就对state+1,代表锁重入。

  3. 以上情况都不是,就加入到等待队列进行等待。

条件变量实现原理

每个条件变量其实就对应着一个等待队列,其实现类是 ConditionObject

读写锁原理

读写锁用的是同一个 Sycn 同步器,因此等待队列state 等也是同一个

  • 读写锁是一种特殊的锁,它包含一个读锁,一个写锁。同一时刻允许多个读线程访问;写线程访问时,所有的读线程和其他的写线程均被阻塞。

  • 读写锁是一种特殊的锁,它包含一个读锁,一个写锁。读锁是支持重进入的共享锁,写锁是支持重进入的排它锁。

  • 由于大多数场景都是多读少写,读写锁比排它锁具有更好并发性和吞吐量。

  • JUC包中,ReentrantReadWriteLock是读写锁的实现。

  • ReentrantReadWriteLock的特性:

  1. 公平性选择: ReentrantReadWriteLock支持公平和非公平获取锁的方式,默认情况为false,即非公平。非公平比公平的吞吐量更高。
  2. 重进入:ReentrantReadWriteLock支持重进入,读线程获取读锁后,能再次获取读锁;写线程获取写锁后,能再次获取写锁或读锁。
  3. 锁降级: 获取写锁、获取读锁再释放写锁,这时写锁能够降级为读锁。
写锁的获取与释放
  • 写锁是支持重进入的排它锁
  • 写锁获取的条件:
  1. 同步状态不为0: 若读锁已经被获取,或当前线程不是已经获取到读锁的线程,则当前线程不能获取写锁并进入阻塞状态;若当前线程为已经获取写锁的线程,直接调用setState()增加写状态。
  2. 同步状态为0: 通过compareAndSetState()方法设置写状态,并设置当前线程为持有写锁的线程。

调用tryAcquire()方法,可以实现写锁的获取:

  • 与ReentrantLock中非公平获取锁的方法相比,当同步状态不为0时,除了判断当前线程是否为持有写锁的线程,还需要增加一个判断条件:读锁是否已经被获取。

  • 读锁被获取后,写锁不能被获取的原因:读锁需要保证写锁的操作对读锁可见。即有读线程已经获取到读锁,如果写线程再获取到写锁,则读线程不会阻塞。因此,读线程无法感知到写线程的操作,不能保证读取到的数据是最新的。

  • 写锁的释放:

  1. 获取了写锁n次,则需要释放写锁n次。
  2. 当写状态为0时,写锁被释放,需要设置持有写锁的线程为null。
读锁的获取和释放
  • 读锁是支持重进入的共享锁
  • 调用tryAcquireShared()方法,可以获取读锁:
  1. 如果其他线程获取到了写锁,则当前线程无法获取到读锁并阻塞
  2. 如果当前线程获取到了写锁,或者写锁未被任何线程获取,则当前线程可以获取到读锁
  3. 当前线程获取到读锁,通过compareAndSetState()实现读状态的增加,每次增加1 << 16。
  4. 由于同一时刻可能有多个线程获取到读锁,依靠CAS保证线程安全。
  • 读锁的释放: 读状态用同步状态的高16 bit表示,释放读锁时,减少的同步状态值不是1,而是1 << 16

  • ReentrantReadWriteLock只支持锁降级,不支持锁升级

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值