The ReentrantReadWriteLock class uses 16 bits of the synchronization state to hold the write lock count, and the remaining 16 bits to hold the read lock count。 The WriteLock is otherwise structured in the same way as ReentrantLock。 The ReadLock uses the acquireShared methods to enable multiple readers。
The Semaphore class (a counting semaphore) uses the synchronization state to hold the current count。 It defines acquireShared to decrement the count or block if nonpositive, and tryRelease to increment the count, possibly unblocking threads if it is now positive。
The CountDownLatch class uses the synchronization state to represent the count。 All acquires pass when it reaches zero。
The FutureTask class uses the synchronization state to represent the run-state of a future (initial, running, cancelled, done)。 Setting or cancelling a future invokes release, unblocking threads waiting for its computed value via acquire。
The SynchronousQueue class (a CSP-style handoff) uses internal wait-nodes that match up producers and consumers。 It uses the synchronization state to allow a producer to proceed when a consumer takes the item, and vice-versa。
Users of the java。util。concurrent package may of course define their own synchronizers for custom applications。 For example, among those that were considered but not adopted in the package are classes providing the semantics of various flavors of WIN32 events, binary latches, centrally managed locks, and tree-based barriers。
(t > 0)? t : t + 0x7fffff
On each iteration a thread updates, with probability S, a shared generator under a mutual exclusion lock, else it updates its own local generator, without a lock。 This results in short-duration locked regions, minimizing extraneous effects when threads are preempted while holding locks。 The randomness of the function serves two purposes: it is used in deciding whether to lock or not (it is a good enough generator for current purposes), and also makes code within loops impossible to trivially optimize away。
Four kinds of locks were compared: Builtin, using synchronized blocks; Mutex, using a simple Mutex class like that illustrated in section 4; Reentrant, using ReentrantLock; and Fair, using ReentrantLock set in its "fair" mode。 All tests used build 46 (approximately the same as beta2) of the Sun J2SE1。5 JDK in "server" mode。 Test programs performed 20 uncontended runs before collecting measurements, to eliminate warm-up effects。 Tests ran for ten million iterations per thread, except Fair mode tests were run only one million iterations。
Tests were performed on four x86-based machines and four UltraSparc-based machines。 All x86 machines were running Linux using a RedHat NPTL-based 2。4 kernel and libraries。 All UltraSparc machines were running Solaris-9。 All systems were at most lightly loaded while testing。 The nature of the tests did not demand that they be otherwise completely idle。 The "4P" name reflects the fact a dual hyperthreaded (HT) Xeon acts more like a 4-way than a 2-way machine。 No attempt was made to normalize across the differences here。 As seen below, the relative costs of synchronization do not bear a simple relationship to numbers of processors, their types, or speeds。
Table 1 Test Platforms
Name Processors Type Speed (Mhz)
1P 1 Pentium3 900
2P 2 Pentium3 1400
2A 2 Athlon 2000
4P