这章来自3.1《Synchronization State》和3.2的《Blocking》。
AbstractQueuedSynchronizer会维护一个Int类型的synchronization state。公开了3个访问和更新state的方法,分别是:getState,setState和compareAndSetState。这些方法依赖java.util.concurrent.atomic和volatile。其中compare-AndSetState实现是依赖于CAS(compare-and-swap)或LL/SC(loadlinked/store-conditional)。CAS大家可能比较熟悉,(current ==expect)则设值。LL/SC则比CAS更严格,(current==expect && current 没有被restore)才算竞争成功。current被restore仍然等于current,CAS是竞争成功的。这是ABA问题。是否觉得LL/SC有点AtomicStampedReference的味道?的确,AtomicStampedReference是通过引进版本号来检测是否被restore。
用一个32位的int来表示synchronization state是一个实用的决定,虽然jsr166提供了64位的long的原子操作,但在一些平台上需要实用内部锁来实现,对性能有所影响。在未来可能引入一个用long来表示synchronization state的基类,但在现在还没有一个足够的理由把这个类包含进来。而且32位的state也满足了大部分应用的需要。只有一个synchronizer CyclicBarrier看起来需要更多的位来表示state。
继承于AbstractQueuedSynchronizer的具体类必须明确的定义tryAcquiretryRelease方法,用来控制acquire和release操作。如果synchronization 被获取,tryAcquire必须返回true。如果新的synchronization state允许以后的acquire,tryRelease也必须返回true。这些方法提供一个int的参数来表示希望的state。例如在一个可重入锁里,就需要计数,但对于大多数的synchronizer是可以忽略这个参数的。
在jsr166前,如果不基于嵌入的monitor,是没有可用的java api去block和unblock一个线程的。唯一的候选方法是Thread.spspend和Thread.resume。但是它们不符合要求,原因是:如果一个unblocking的线程在调用suspend被阻塞前调用了resume是没有效果的(这里是希望,如果在调用suspend前resume先被调用,suspend不会导致线程挂起)。
在并发包里包含了一个LockSupport的类,该类解决了这个问题。方法LockSupport.park会block当前线程,除非或直到LockSupport.unpark被调用。unpark的调用是不会被计数的,所以多次unpark只会影响之后的第一次park。然后这些应用是针对每个thread的,而不是每个synchronizer。一个thread在一个新的synchronizer调用了park可能马上返回,因为unpark在之前被调用了。如果没有unpark,那么下次调用park就会导致thread阻塞。可能会需要一个操作去清理thread 的state,使park可以阻塞thread,但是其实不需要这么做,在需要的情况下,多调用几次park更高效。
在某些程度上,这个简单的原理看上去和某些平台的某些机制很相像,例如在Solaris-9的thread library,windows的“consumeable events”,Linux NPTL thread library。park和unpark可以高效的映射到这些常见的支持jvm的平台上。park也支持相对和绝对的超时时间,并且可以和Thead.interrupt结合,interrupt一个thread可以unpark它。
分享到:
相关推荐
concurrent Synchronizer Framework,讲解整个并发框架的设计思路!
The java.util.concurrent synchronizer framework from Doug Lea
AQS作者Doug lea关于AQS设计、性能的paper,需要了解AQS的设计思想,思路可以参考这篇paper
Light, concurrent RPC framework for PHP & C
The java.util.concurrent Synchronizer Framework
这个工程是为了学习guava concurrent中的AbstractFuture而建立的,里面有可以运行的例子,再配合我的博客:https://blog.csdn.net/o1101574955/article/details/82889851,可以看明白guava concurrent的基本设计思路...
CoDeK-Java并发开发frameworK是一个非常简单的开源学术Java库,旨在帮助开发Java多线程并发应用程序。
backport-util-concurrent.jarbackport-util-concurrent.jarbackport-util-concurrent.jar
Chapter 2. Concurrency on the JVM and the Java Memory Model Chapter 3. Traditional Building Blocks of Concurrency Chapter 4. Asynchronous Programming with Futures and Promises Chapter 5. Data-Parallel...
Inside the Oracle Concurrent Manager
Windows并发编程指南 Concurrent Programming on Windows (english)part2Joe Duffy是Microsoft公司.NET框架团队中并行扩展功能的技术主管、架构师以及奠基者,就职于Visual Studio部门。除了编写代码和管理开发团队...
Concurrent.Thread.js 一个用来让javascript也进行多线程开发的包,感兴趣的快来下吧。
concurrent.jar web开发工具包
concurrent 源代码concurrent 源代码
Simplx is a C++ development framework for building reliable cache-friendly distributed and concurrent multicore software. Simplx was developped by Tredzone SAS. We provide software technology ...
2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞...
concurrent-1.3.4.jar
concurrent.jar 里面有,使用Apache JCS 时候需要的EDU/oswego/cs/dl/util/concurrent/Channel ,编译 jcaptcha时候需要第EDU.oswego.cs.dl.util.concurrent.ClockDaemon类, concurrent-1.3.3.jar