Java并发包的理解

并发包相对于Synchronize的优势

并发包相对于synchronize而言,
功能性上:提供了获取与释放锁的可操作性。支持非阻塞式、可中断以及超时获取锁的机制。
性能上:使用volatile与CAS是种乐观锁的思想,避免直接使用重量级的锁,避免了多个线程被迫串行以及上下文切换过程,提高了并发性能。
缺陷:只适用于单机版本,无法适用于多机服务。

AQS理解

并发包提供的各种锁比如可重入锁、读写锁等的底层是通过AQS实现的。

AQS解决了实现锁时涉及当的大量细节问题,例如获取锁的同步状态(通过volatile变量 + CAS操作实现)、维护了与synchronize对等的两个队列(锁池队列以及等待队列(多个等待队列)),并且支持公平锁与非公平锁的机制。AQS底层是volatile以及CAS,这里处理了CAS操作的大量细节,比如队列状态维护,线程休眠时间控制等。
基于AQS来构建同步器可以带来很多好处。它不仅能够极大地减少实现工作,而且也不必处理在多个位置上发生的竞争问题。

AQS具体介绍:《并发编程的艺术》p121

AQS实现自定义锁的要点

实现的核心点:

  1. get、set、compareAndSetState接口获取以及设置锁的同步状态Volatile state变量。
  2. 提供tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared等接口,具体实现独占锁以及共享锁
    提供acquire、acquired等模板方法,这些模板方法分为三类:独占式获取与释放、共享式获取与释放、查询同步队列情况等方法。方便直接调用
    这里就是一种模板模式,abstract抽象类,提供了抽象方法让用户去自己实现从而定义自己的锁。

并发包同步队列底层总结

同步队列的核心点:
head、tail是volatile保持可见性与有序性,通过compareAndSetTail与casHead保证操作的原子性
添加节点的时候是自旋操作,不涉及任何的线程休眠

在AQS提供的acquire方法中,
添加到同步队列之后,node等待成为头结点的后继节点之后,尝试casState,一旦成功即为获取到锁,此时将自己更新为头结点
如果非头节点,则会使用lockSupport让当前线程休眠,退出时间片的竞争。
在release方法中,会去唤醒同步队列head节点的一个节点,唤醒休眠态的节点。

这里自旋会首先判断自己是否是头结点,原因:维持FIFO、防止伪唤醒迅速判定状态然后继续休眠。
公平与否的实现就是看是否要做头结点的判断,如果不公平,则是直接去tryAcquire。

关于共享锁的实现,与独占锁之间的区别就在于volatile state的不同,独占锁是0,1,共享锁是比1大的数字,从而支持重入,支持读写分离。
在state为0的时候意味着没有任何线程获取到锁,非0的时候意味着有线程获取到锁,然后进行后续判断与处理即可,比如可重入的话就判断线程是否相同。
读写锁则是利用了int的高低位之间的区别,从而完成读写状态的判断。

并发包对wait、notify机制的优化:

之前的object的wait-notify机制,只支持一个object.wait
lock可以设置多个等待队列,new 多个condition即可。

阻塞队列:
常用于生产者消费者模式

参考

AQS介绍:
https://juejin.im/entry/5ae02a7c6fb9a07ac76e7b70

LinkedBlockingQueue源码分析与api介绍:
https://blog.csdn.net/tonywu1992/article/details/83419448
https://blog.csdn.net/weixin_41771218/article/details/83056052

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值