Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
醒狮指南
JavaGuide
提交
0559dec5
J
JavaGuide
项目概览
醒狮指南
/
JavaGuide
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JavaGuide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
0559dec5
编写于
3月 21, 2020
作者:
S
shuang.kou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update AQS.md
上级
78e91223
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
13 addition
and
4 deletion
+13
-4
docs/java/Multithread/AQS.md
docs/java/Multithread/AQS.md
+13
-4
未找到文件。
docs/java/Multithread/AQS.md
浏览文件 @
0559dec5
...
...
@@ -327,11 +327,10 @@ CountDownLatch允许 count 个线程阻塞在一个地方,直至所有线程
CountDownLatch是共享锁的一种实现,它默认构造 AQS 的 state 值为 count。当线程使用countDown方法时,其实使用了
`tryReleaseShared`
方法以CAS的操作来减少state,直至state为0就代表所有的线程都调用了countDown方法。当调用await方法的时候,如果state不为0,就代表仍然有线程没有调用countDown方法,那么就把已经调用过countDown的线程都放入阻塞队列Park,并自旋CAS判断state == 0,直至最后一个线程调用了countDown,使得state == 0,于是阻塞的线程便判断成功,全部往下执行。
#### 4.1 CountDownLatch 的
三
种典型用法
#### 4.1 CountDownLatch 的
两
种典型用法
1.
某一线程在开始运行前等待 n 个线程执行完毕。将 CountDownLatch 的计数器初始化为 n :
`new CountDownLatch(n)`
,每当一个任务线程执行完毕,就将计数器减 1
`countdownlatch.countDown()`
,当计数器的值变为 0 时,在
`CountDownLatch上 await()`
的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
2.
实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的
`CountDownLatch`
对象,将其计数器初始化为 1 :
`new CountDownLatch(1)`
,多个线程在开始执行任务前首先
`coundownlatch.await()`
,当主线程调用 countDown() 时,计数器变为 0,多个线程同时被唤醒。
3.
死锁检测:一个非常方便的使用场景是,你可以使用 n 个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
#### 4.2 CountDownLatch 的使用示例
...
...
@@ -382,7 +381,17 @@ public class CountDownLatchExample1 {
与 CountDownLatch 的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用
`CountDownLatch.await()`
方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
其他 N 个线程必须引用闭锁对象,因为他们需要通知 CountDownLatch 对象,他们已经完成了各自的任务。这种通知机制是通过 CountDownLatch.countDown()方法来完成的;每调用一次这个方法,在构造函数中初始化的 count 值就减 1。所以当 N 个线程都调 用了这个方法,count 的值等于 0,然后主线程就能通过 await()方法,恢复执行自己的任务。
其他 N 个线程必须引用闭锁对象,因为他们需要通知
`CountDownLatch`
对象,他们已经完成了各自的任务。这种通知机制是通过
`CountDownLatch.countDown()`
方法来完成的;每调用一次这个方法,在构造函数中初始化的 count 值就减 1。所以当 N 个线程都调 用了这个方法,count 的值等于 0,然后主线程就能通过
`await()`
方法,恢复执行自己的任务。
再插一嘴:
`CountDownLatch`
的
`await()`
方法使用不当很容易产生死锁,比如我们上面代码中的 for 循环改为:
```
java
for
(
int
i
=
0
;
i
<
threadCount
-
1
;
i
++)
{
.......
}
```
这样就导致
`count`
的值没办法等于 0,然后就会导致一直等待。
如果对CountDownLatch源码感兴趣的朋友,可以查看:
[
【JUC】JDK1.8源码分析之CountDownLatch(五)
](
https://www.cnblogs.com/leesf456/p/5406191.html
)
...
...
@@ -390,7 +399,7 @@ public class CountDownLatchExample1 {
CountDownLatch 是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当 CountDownLatch 使用完毕后,它不能再次被使用。
#### 4.4 CountDownLatch 相常见面试题
:
#### 4.4 CountDownLatch 相常见面试题
解释一下 CountDownLatch 概念?
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录