Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于AQS组件部分的文章的错误 #645

Closed
guang19 opened this issue Feb 19, 2020 · 11 comments
Closed

关于AQS组件部分的文章的错误 #645

guang19 opened this issue Feb 19, 2020 · 11 comments
Labels
bug Content error enhancement New feature or request or suggestion

Comments

@guang19
Copy link
Contributor

guang19 commented Feb 19, 2020

image

如上图:
关于文章中的:
“ Semaphore(信号量)可以指定多个线程同时访问某个资源。”
这句话在我阅读源码后发现,Semaphore 可以指定一次性可以指定最多 permits个线程执行任务,而不是 : "同时",因为Semaphore它的实现是只要AQS的state>0 == true,那么线程通过不断自旋CAS,就有机会获得执行任务的机会,所以只要在线程自旋期间,state是大于0的,那么任何一个线程都有可能判断成功,而不是多个线程同时成功。。

然后关于这部分AQS组件的描述个人认为有点模糊不清,所以我在整理后重新组织了下语言:

CountDownLatch

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,
于是阻塞的线程便判断成功,全部往下执行。

Semaphore

Semaphore允许一次性最多(不是同时)permits个线程执行任务。

Semaphore与CountDownLatch一样,也是共享锁的一种实现。
它默认构造AQS的state为permits。当执行任务的线程数量超出permits,那么多余的线程将会被放入阻塞队列Park,并自旋判断state是否大于0。
只有当state大于0的时候,阻塞的线程才能继续执行,此时先前执行任务的线程继续执行release方法,
release方法使得state的变量会加1,那么自旋的线程便会判断成功。
如此,每次只有最多不超过permits数量的线程能自旋成功,便限制了执行任务线程的数量。

所以这也是我为什么说它可能不是permits个线程同时执行,
因为只要state>0,线程就有机会执行.

CycliBarrier

CycliBarrier的功能与CountDownLatch相似,但是CountDownLatch的实现是基于AQS的,
而CycliBarrier是基于ReentrantLock(ReentrantLock也属于AQS同步器)和Condition的.

CountDownLatch虽然可以令线程阻塞,但是CountDownLatch只能await一次就不能使用了,
而CycliBarrier有Generation代的概念,一个代,就代表CycliBarrier的一个循环,
这也是CycliBarrier支持重复await的原因。

老哥可以选择性的更改下错误的部分。。。

@Snailclimb Snailclimb added the bug Content error label Feb 26, 2020
@Snailclimb
Copy link
Owner

收到!

@Snailclimb Snailclimb added the enhancement New feature or request or suggestion label Mar 13, 2020
@Snailclimb
Copy link
Owner

同时

@fastkeeper
Copy link

CountDownLatch允许 count 个线程阻塞在一个地方,直至所有线程的任务都执行完毕。

拜读了上面楼主写的东西,我对这句话有些疑惑,CountDownLatch不应该是允许一到多个线程阻塞,直至count个线程的任务完成,然后唤醒阻塞的线程嘛,烦请解释!

@guang19
Copy link
Contributor Author

guang19 commented Mar 27, 2020

CountDownLatch允许 count 个线程阻塞在一个地方,直至所有线程的任务都执行完毕。

拜读了上面楼主写的东西,我对这句话有些疑惑,CountDownLatch不应该是允许一到多个线程阻塞,直至count个线程的任务完成,然后唤醒阻塞的线程嘛,烦请解释!

不好意思,我的描述确实有问题,给各位造成误解了。。

应该是允许多个线程阻塞,直至count个线程执行完毕,然后unpark阻塞的线程。

@fastkeeper
Copy link

fastkeeper commented Mar 27, 2020 via email

@guang19
Copy link
Contributor Author

guang19 commented Mar 27, 2020

我关于CountDownLatch的说法和你的是一样的,但是你的的确准确一些,以后我会组织好语言的。

至于你说的CountDownLatch和CyclicBarrier的区别,这个我觉得看个人理解吧,CountDownLatch使用的是AQS实现的,CyclicBarrier使用的是ReentrantLock实现的,虽然都属于AQS,但这也是它们一个不同点吧,CyclicBarrier的实现更复杂写。在我看来,对它们最最最简单的理解就是CyclicBarrier可以允许多次阻塞,而CountDownLatch只能够阻塞一次。

@fastkeeper
Copy link

fastkeeper commented Mar 27, 2020 via email

@guang19
Copy link
Contributor Author

guang19 commented Mar 27, 2020

没事没事,就是对于我这种人可能理解能力没那么强,容易误解。

------------------ 原始邮件 ------------------ 发件人: "YangGuang"<[email protected]>; 发送时间: 2020年3月27日(星期五) 中午11:43 收件人: "Snailclimb/JavaGuide"<[email protected]>; 抄送: "张亚川"<[email protected]>; "Comment"<[email protected]>; 主题: Re: [Snailclimb/JavaGuide] 关于AQS组件部分的文章的错误 (#645) 我关于CountDownLatch的说法和你的是一样的,但是你的的确准确一些,以后我会组织好语言的。 至于你说的CountDownLatch和CyclicBarrier的区别,这个我觉得看个人理解吧,CountDownLatch使用的是AQS实现的,CyclicBarrier使用的是ReentrantLock实现的,虽然都属于AQS,但这也是它们一个不同点吧,CyclicBarrier的实现更复杂写。在我看来,对它们最最最简单的理解就是CyclicBarrier可以允许多次阻塞,而CountDownLatch只能够阻塞一次。 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

我也是。这个是我正在写的一份开源文档资料,如果你有好的想法,可以pr: framework-learning

@fastkeeper
Copy link

fastkeeper commented Mar 27, 2020 via email

@guang19
Copy link
Contributor Author

guang19 commented Mar 27, 2020

感谢!!!

@Hogantry
Copy link

Hogantry commented Jun 11, 2020

嗯嗯,还有,关于CountDownLatch。当调用await方法的时候,如果state不为0,就代表仍然有线程没有调用countDown方法,那么就把已经调用过countDown的线程都放入阻塞队列Park,并自旋CAS判断state == 0,直至最后一个线程调用了countDown,使得state == 0,于是阻塞的线程便判断成功,全部往下执行。


将调用过countDown的线程都放入阻塞队列Park,改成将所有调用await的线程都放入阻塞队列Park

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Content error enhancement New feature or request or suggestion
Projects
None yet
Development

No branches or pull requests

4 participants