JUC_AQS_概念最最基础入门(高手莫进)

22 篇文章 0 订阅
3 篇文章 0 订阅
JUC是JAVA推出顶替synchronize的jar包

JUC : java.util.concurrent 也就是java并发工具包
里面含有线程池, 阻塞队列,同步器,计时器等组件 etc…

OK 以上关于JUC 的定位已经了解了,那么既然JUC 想要代替synchronize关键字,那么关键 就在与 lock(锁)

然而既然实现锁,那么有两点肯定是避不开的

1) 线程如何争抢锁?

2) 线程争抢锁失败以后,该如何处理?



1) 线程如何争抢锁?
锁 一般有两个特性可以被称之为锁:
1) 共享性
2) 排他性
所以在争抢锁的时候,那么这个锁一定在在多个线程中共享的, 我们所要做的就是如何保证它在争抢锁时的一个安全性.

在java中有一种实现方式被称之为CAS 使用的是 乐观锁的理念

所谓的乐观锁 以java的实现如下:

入参: 对象, 内存值, 预期值, 更新值
其中 对象即为被多个线程共享的锁对象
内存值 就是锁状态在内存中存在的位置
假设当前 锁状态的含义为:
	0 代表锁是没有被占用
	1 代表当前锁已被占用
那么在乐观锁中 预期值就是 0 ,更新值就是 1
判断逻辑:
	1) 使用预期值 与 内存中的锁状态做对比
	2) 如果返回true代表当前锁没有被占用, 
		即修改成 参数中的更新值
	3) 如果返回false就算作争抢失败
(ps: java中的CAS最后的调用的是 native中的本地函数实现的
	在此不做展开)

2) 线程争抢锁失败以后,该如何处理?

在线程争抢锁失败之后, 总不能不管线程,让其跳过当前代码块,走下面的流程.

因此我们需要一个线程管理者,

在JUC里面这个管理者 被称之为AQS.

其实现方式为双向链表,

AQS的工作逻辑如下:

1) 当ThreadA 与ThreadB 互相争抢锁

2) ThreadA争抢锁成功,将其作为AQS head节点

3) 将其放入AQS队列,在放入AQS队列之前抢一次锁

4) ThreadB 争抢锁失败,在只有两个线程的情况下 ThreadB 是作为 ThreadA 的next 存贮在AQS队列中

5) 对ThreadB 的node节点 使用自旋,死循环抢锁

6) 短暂时间片之后,如果没有抢到锁将调用 park函数将线程挂起

7) 当ThreadA 执行完毕释放锁之后,唤醒 next 节点 ,
在这里也就是 ThreadB节点

8) ThreadB节点进行锁的争抢,如果抢夺成功 则将 
ThreadB节点设置为AQS队列的head 节点 
(ps: 谁抢夺锁成功谁就是 AQS队列中的head节点)

由以上粗略的工作逻辑我们可以大致了解下 AQS是如何工作的, 也了解了在JUC之中 如果线程抢不到锁, 是被如何分配的


题外话:

在java中 实现lock接口的有 ReentrantLock

实现依赖AQS队列的有 FairSync(公平锁) 与 NonfairSync(非公平锁)
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:博客之星2020 设计师:CSDN官方博客 返回首页
评论

打赏作者

评论有风险,起名需谨慎

你冷漠的走过不留下一点C币

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值