vi Java Concurrency In Practice Listing 3.15.Class at Risk of Failure if Not Properly Published. 34 Chapter 4.Composing objects 31 Listing 4.1.Simple Thread-safe Counter Using the Java Monitor Pattern. 31 Listing 4.2.Using Confinement to Ensure Thread Safety. 9 Listing 4.3.Guarding State with a Private Lock. 40 Listing 4.4.Monitor-based Vehicle Tracker Implementation. 42 Listing 4.5.Mutable Point Class Similar to Java.awt.Point. 42 Listing 4.6.Immutable Point class used by DelegatingvehicleTracker. 42 Listing 4.7.Delegating Thread Safety to a ConcurrentHashMap. 43 Listing 4.8.Returning a Static Copy of the Location Set Instead of a"Live"One. 43 Listing 4.9.Delegating Thread Safety to Multiple Underlying State Variables. 44 Listing 4.10.Number Range Class that does Not Sufficiently Protect Its Invariants.Don't Do this. 45 Listing 4.11.Thread-safe Mutable Point Class. 45 Listing 4.12.Vehicle Tracker that Safely Publishes Underlying State. 46 Listing 4.13.Extending Vector to have a Put-if-absent Method. A7 Listing 4.14.Non-thread-safe Attempt to Implement Put-if-absent.Don't Do this. 48 Listing 4.15.Implementing Put-if-absent with Client-side Locking. 48 Listing 4.16.Implementing Put-if-absent Using Composition 49 Chapter 5.Building Blocks 51 Listing 5.1.Compound Actions on a vector that may Produce Confusing Results. 51 Figure 5.1.Interleaving of Getlast and Deletelast that throws ArrayIndexoutofBoundsException. 51 Listing 5.2.Compound Actions on Vector Using Client-side Locking. 52 Listing 5.3.Iteration that may Throw ArrayIndexoutofBoundsException. 52 Listing 5.4.Iteration with Client-side Locking. 52 Listing 5.5.Iterating a List with an Iterator. 53 Listing 5.6.Iteration Hidden within String Concatenation.Don't Do this. 54 Listing 5.7.ConcurrentMap Interface. 56 Listing 5.8.Producer and Consumer Tasks in a Desktop Search Application. 58 Listing 5.9.Starting the Desktop Search. 58 Listing 5.10.Restoring the Interrupted Status so as Not to Swallow the Interrupt. 60 Listing 5.11.Using CountDownLatch for Starting and Stopping Threads in Timing Tests. 61 Listing 5.12.Using FutureTask to Preload Data that is Needed Later. 62 Listing 5.13.Coercing an Unchecked Throwable to a RuntimeException. 62 Listing 5.14.Using Semaphore to Bound a Collection. 64
vi Java Concurrency In Practice Listing 3.15. Class at Risk of Failure if Not Properly Published. 34 Chapter 4. Composing Objects 37 Listing 4.1. Simple ThreadͲsafe Counter Using the Java Monitor Pattern. 37 Listing 4.2. Using Confinement to Ensure Thread Safety. 39 Listing 4.3. Guarding State with a Private Lock. 40 Listing 4.4. MonitorͲbased Vehicle Tracker Implementation. 42 Listing 4.5. Mutable Point Class Similar to Java.awt.Point. 42 Listing 4.6. Immutable Point class used by DelegatingVehicleTracker. 42 Listing 4.7. Delegating Thread Safety to a ConcurrentHashMap. 43 Listing 4.8. Returning a Static Copy of the Location Set Instead of a "Live" One. 43 Listing 4.9. Delegating Thread Safety to Multiple Underlying State Variables. 44 Listing 4.10. Number Range Class that does Not Sufficiently Protect Its Invariants. Don't Do this. 45 Listing 4.11. ThreadͲsafe Mutable Point Class. 46 Listing 4.12. Vehicle Tracker that Safely Publishes Underlying State. 46 Listing 4.13. Extending Vector to have a PutͲifͲabsent Method. 47 Listing 4.14. NonͲthreadͲsafe Attempt to Implement PutͲifͲabsent. Don't Do this. 48 Listing 4.15. Implementing PutͲifͲabsent with ClientͲside Locking. 48 Listing 4.16. Implementing PutͲifͲabsent Using Composition. 49 Chapter 5. Building Blocks 51 Listing 5.1. Compound Actions on a Vector that may Produce Confusing Results. 51 Figure 5.1. Interleaving of Getlast and Deletelast that throws ArrayIndexOutOfBoundsException. 51 Listing 5.2. Compound Actions on Vector Using ClientͲside Locking. 52 Listing 5.3. Iteration that may Throw ArrayIndexOutOfBoundsException. 52 Listing 5.4. Iteration with ClientͲside Locking. 52 Listing 5.5. Iterating a List with an Iterator. 53 Listing 5.6. Iteration Hidden within String Concatenation. Don't Do this. 54 Listing 5.7. ConcurrentMap Interface. 56 Listing 5.8. Producer and Consumer Tasks in a Desktop Search Application. 58 Listing 5.9. Starting the Desktop Search. 58 Listing 5.10. Restoring the Interrupted Status so as Not to Swallow the Interrupt. 60 Listing 5.11. Using CountDownLatch for Starting and Stopping Threads in Timing Tests. 61 Listing 5.12. Using FutureTask to Preload Data that is Needed Later. 62 Listing 5.13. Coercing an Unchecked Throwable to a RuntimeException. 62 Listing 5.14. Using Semaphore to Bound a Collection. 64
1BListing and Image Index Listing 5.15.Coordinating Computation in a Cellular Automaton with 64 Listing 5.16.Initial Cache Attempt Using HashMap and Synchronization. 66 Figure 5.2.Poor Concurrency of 66 Figure 5.3.Two Threads Computing the Same Value When Using 61 Listing 5.17.Replacing HashMap with ConcurrentHashMap. 61 Figure 5.4.Unlucky Timing that could Cause Memorizer3 to Calculate the Same Value Twice. 68 Listing 5.18.Memorizing Wrapper Using FutureTask. Listing 5.19.Final Implementation of Memorizer. 69 Listing 5.20.Factorizing Servlet that Caches Results Using Memorizer 69 Chapter 6,Task Execution 72 Listing 6.1.Sequential Web Server. 72 Listing 6.2.Web Server that Starts a New Thread for Each Request. 73 Listing 6.3.Executor Interface. 74 Listing 6.4.Web Server Using a Thread Pool. 75 Listing 6.5.Executor that Starts a New Thread for Each Task. 75 Listing 6.6.Executor that Executes Tasks Synchronously in the Calling Thread. 75 Listing 6.7.Lifecycle Methods in ExecutorService. 71 Listing 6.8.Web Server with Shutdown Support. 77 Listing 6.9.Class Illustrating Confusing Timer Behavior. 78 Listing 6.10.Rendering Page Elements Sequentially. 79 Listing 6.11.Callable and Future Interfaces. 80 Listing 6.12.Default Implementation of newTaskFor in ThreadPoolExecutor. 80 Listing 6.13.Waiting for Image Download with Future. 81 Listing 6.14.QueueingFuture Class Used By Executorcompletionservice 82 Listing 6.15.Using Completionservice to Render Page Elements as they Become Available. 82 Listing 6.16.Fetching an Advertisement with a Time Budget. 83 Listing 6.17.Requesting Travel Quotes Under a Time Budget. 84 Chapter 7.Cancellation and Shutdown 85 Listing 7.1.Using a Volatile Field to Hold Cancellation State. 86 Listing 7.2.Generating a Second's Worth of Prime Numbers. 86 Listing 7.3.Unreliable Cancellation that can Leave Producers Stuck in a Blocking Operation.Don't Do this. 8☑ Listing 7.4.Interruption Methods in Thread. 87 Listing 7.5.Using Interruption for Cancellation 88 Listing 7.6.Propagating InterruptedException to Callers. 89 Listing 7.7.Non-cancelable Task that Restores Interruption Before Exit. 90 Listing 7.8.Scheduling an Interrupt on a Borrowed Thread.Don't Do this. 90
1BListing and Image Index vii Listing 5.15. Coordinating Computation in a Cellular Automaton with 64 Listing 5.16. Initial Cache Attempt Using HashMap and Synchronization. 66 Figure 5.2. Poor Concurrency of 66 Figure 5.3. Two Threads Computing the Same Value When Using 67 Listing 5.17. Replacing HashMap with ConcurrentHashMap. 67 Figure 5.4. Unlucky Timing that could Cause Memorizer3 to Calculate the Same Value Twice. 68 Listing 5.18. Memorizing Wrapper Using FutureTask. 68 Listing 5.19. Final Implementation of Memorizer. 69 Listing 5.20. Factorizing Servlet that Caches Results Using Memorizer. 69 Chapter 6. Task Execution 72 Listing 6.1. Sequential Web Server. 72 Listing 6.2. Web Server that Starts a New Thread for Each Request. 73 Listing 6.3. Executor Interface. 74 Listing 6.4. Web Server Using a Thread Pool. 75 Listing 6.5. Executor that Starts a New Thread for Each Task. 75 Listing 6.6. Executor that Executes Tasks Synchronously in the Calling Thread. 75 Listing 6.7. Lifecycle Methods in ExecutorService. 77 Listing 6.8. Web Server with Shutdown Support. 77 Listing 6.9. Class Illustrating Confusing Timer Behavior. 78 Listing 6.10. Rendering Page Elements Sequentially. 79 Listing 6.11. Callable and Future Interfaces. 80 Listing 6.12. Default Implementation of newTaskFor in ThreadPoolExecutor. 80 Listing 6.13. Waiting for Image Download with Future. 81 Listing 6.14. QueueingFuture Class Used By ExecutorCompletionService. 82 Listing 6.15. Using CompletionService to Render Page Elements as they Become Available. 82 Listing 6.16. Fetching an Advertisement with a Time Budget. 83 Listing 6.17. Requesting Travel Quotes Under a Time Budget. 84 Chapter 7. Cancellation and Shutdown 85 Listing 7.1. Using a Volatile Field to Hold Cancellation State. 86 Listing 7.2. Generating a Second's Worth of Prime Numbers. 86 Listing 7.3. Unreliable Cancellation that can Leave Producers Stuck in a Blocking Operation. Don't Do this. 87 Listing 7.4. Interruption Methods in Thread. 87 Listing 7.5. Using Interruption for Cancellation. 88 Listing 7.6. Propagating InterruptedException to Callers. 89 Listing 7.7. NonͲcancelable Task that Restores Interruption Before Exit. 90 Listing 7.8. Scheduling an Interrupt on a Borrowed Thread. Don't Do this. 90
vili Java Concurrency In Practice Listing 7.9.Interrupting a Task in a Dedicated Thread. 91 Listing 7.10.Cancelling a Task Using Future. 92 Listing 7.11.Encapsulating Nonstandard Cancellation in a Thread by Overriding Interrupt. 93 Listing 7.12.Encapsulating Nonstandard Cancellation in a Task with Newtaskfor. 94 Listing 7.13.Producer-Consumer Logging Service with No Shutdown Support. 95 Listing 7.14.Unreliable Way to Add Shutdown Support to the Logging Service. 95 Listing 7.15.Adding Reliable Cancellation to Logwriter. 96 Listing 7.16.Logging Service that Uses an Executorservice. 97 Listing 7.17.Shutdown with Poison Pill 92 Listing 7.18.Producer Thread for IndexingService. 98 Listing 7.19.Consumer Thread for Indexingservice. 98 Listing 7.20.Using a Private Executor Whose Lifetime is Bounded by a Method Call. 98 Listing 7.21.Executorservice that Keeps Track of Cancelled Tasks After Shutdown 99 Listing 7.22.Using TRackingExecutorservice to Save Unfinished Tasks for Later Execution. 100 Listing 7.23.Typical Thread-pool Worker Thread Structure. 101 Listing 7.24.UncaughtExceptionHandler Interface. 101 Listing 7.25.UncaughtExceptionHandler that Logs the Exception. 101 Listing 7.26.Registering a Shutdown Hook to Stop the Logging Service. 103 Chapter 8.Applying Thread Pools 104 Listing 8.1.Task that Deadlocks in a Single-threaded Executor.Don't Do this. 105 Listing 8.2.General Constructor for ThreadPoolExecutor. 10Z Listing 8.3.Creating a Fixed-sized Thread Pool with a Bounded Queue and the Caller-runs Saturation Policy.109 Listing 8.4.Using a Semaphore to Throttle Task Submission. 109 Listing 8.5.ThreadFactory Interface. 109 Listing 8.6.Custom Thread Factory. 110 Listing 8.7.Custom Thread Base Class. 111 Listing 8.8.Modifying an Executor Created with the Standard Factories. 111 Listing 8.9.Thread Pool Extended with Logging and Timing. 112 Listing 8.10.Transforming Sequential Execution into Parallel Execution. 112 Listing 8.11.Transforming Sequential Tail-recursion into Parallelized Recursion. 113 Listing 8.12.Waiting for Results to be Calculated in Parallel. 113 Listing 8.13.Abstraction for Puzzles Like the "Sliding Blocks Puzzle". 113 Listing 8.14.Link Node for the Puzzle Solver Framework. 114 Listing 8.15.Sequential Puzzle Solver. 115 Listing 8.16.Concurrent Version of Puzzle Solver. 115 Listing 8.17.Result-bearing Latch Used by ConcurrentPuzzlesolver. 116
viii Java Concurrency In Practice Listing 7.9. Interrupting a Task in a Dedicated Thread. 91 Listing 7.10. Cancelling a Task Using Future. 92 Listing 7.11. Encapsulating Nonstandard Cancellation in a Thread by Overriding Interrupt. 93 Listing 7.12. Encapsulating Nonstandard Cancellation in a Task with Newtaskfor. 94 Listing 7.13. ProducerͲConsumer Logging Service with No Shutdown Support. 95 Listing 7.14. Unreliable Way to Add Shutdown Support to the Logging Service. 95 Listing 7.15. Adding Reliable Cancellation to LogWriter. 96 Listing 7.16. Logging Service that Uses an ExecutorService. 97 Listing 7.17. Shutdown with Poison Pill. 97 Listing 7.18. Producer Thread for IndexingService. 98 Listing 7.19. Consumer Thread for IndexingService. 98 Listing 7.20. Using a Private Executor Whose Lifetime is Bounded by a Method Call. 98 Listing 7.21. ExecutorService that Keeps Track of Cancelled Tasks After Shutdown. 99 Listing 7.22. Using TRackingExecutorService to Save Unfinished Tasks for Later Execution. 100 Listing 7.23. Typical ThreadͲpool Worker Thread Structure. 101 Listing 7.24. UncaughtExceptionHandler Interface. 101 Listing 7.25. UncaughtExceptionHandler that Logs the Exception. 101 Listing 7.26. Registering a Shutdown Hook to Stop the Logging Service. 103 Chapter 8. Applying Thread Pools 104 Listing 8.1. Task that Deadlocks in a SingleͲthreaded Executor. Don't Do this. 105 Listing 8.2. General Constructor for ThreadPoolExecutor. 107 Listing 8.3. Creating a FixedͲsized Thread Pool with a Bounded Queue and the CallerͲruns Saturation Policy. 109 Listing 8.4. Using a Semaphore to Throttle Task Submission. 109 Listing 8.5. ThreadFactory Interface. 109 Listing 8.6. Custom Thread Factory. 110 Listing 8.7. Custom Thread Base Class. 111 Listing 8.8. Modifying an Executor Created with the Standard Factories. 111 Listing 8.9. Thread Pool Extended with Logging and Timing. 112 Listing 8.10. Transforming Sequential Execution into Parallel Execution. 112 Listing 8.11. Transforming Sequential TailͲrecursion into Parallelized Recursion. 113 Listing 8.12. Waiting for Results to be Calculated in Parallel. 113 Listing 8.13. Abstraction for Puzzles Like the "Sliding Blocks Puzzle". 113 Listing 8.14. Link Node for the Puzzle Solver Framework. 114 Listing 8.15. Sequential Puzzle Solver. 115 Listing 8.16. Concurrent Version of Puzzle Solver. 115 Listing 8.17. ResultͲbearing Latch Used by ConcurrentPuzzleSolver. 116
1BListing and Image Index Listing 8.18.Solver that Recognizes when No Solution Exists. 116 Chapter 9 GUl Applications 11Z Figure 9.1.Control Flow of a Simple Button Click. 119 Listing 9.1.Implementing SwingUtilities Using an Executor. 120 Listing 9.2.Executor Built Atop SwingUtilities. 120 Listing 9.3.Simple Event Listener. 120 Figure 9.2.Control Flow with Separate Model and View Objects. 121 Listing 9.4.Binding a Long-running Task to a Visual Component. 121 Listing 9.5.Long-running Task with User Feedback. 122 Listing 9.6.Cancelling a Long-running Task. 122 Listing 9.7.Background Task Class Supporting Cancellation,Completion Notification,and Progress Notification. 124 Listing 9.8.Initiating a Long-running,Cancellable Task with BackgroundTask. 124 Chapter 10.Avoiding Liveness Hazards 128 Figure 10.1.Unlucky Timing in LeftRightDeadlock. 128 Listing 10.1.Simple Lock-ordering Deadlock.Don't Do this. 129 Listing 10.2.Dynamic Lock-ordering Deadlock.Don't Do this. 129 Listing 10.3.Inducing a Lock Ordering to Avoid Deadlock. 130 Listing 10.4.Driver Loop that Induces Deadlock Under Typical Conditions. 131 Listing 10.5.Lock-ordering Deadlock Between Cooperating Objects.Don't Do this. 132 Listing 10.6.Using Open Calls to Avoiding Deadlock Between Cooperating Objects. 133 Listing 10.7.Portion of Thread Dump After Deadlock. 135 Chapter 11.Performance and Scalability 13Z Figure 11.1.Maximum Utilization Under Amdahl's Law for Various Serialization Percentages. 140 Listing 11.1.Serialized Access to a Task Queue. 141 Figure 11.2.Comparing Queue Implementations. 141 Listing 11.2.Synchronization that has No Effect.Don't Do this. 142 Listing 11.3.Candidate for Lock Elision. 143 Listing 11.4.Holding a Lock Longer than Necessary. 145 Listing 11.5.Reducing Lock Duration. 145 Listing 11.6.Candidate for Lock Splitting. 146 Listing 11.7.Serverstatus Refactored to Use Split Locks. 145 Listing 11.8.Hash-based Map Using Lock Striping. 148 Figure 11.3.Comparing Scalability of Map Implementations. 150 Chapter 12.Testing Concurrent Programs 153 Listing 12.1.Bounded Buffer Using Semaphore. 154
1BListing and Image Index ix Listing 8.18. Solver that Recognizes when No Solution Exists. 116 Chapter 9. GUI Applications 117 Figure 9.1. Control Flow of a Simple Button Click. 119 Listing 9.1. Implementing SwingUtilities Using an Executor. 120 Listing 9.2. Executor Built Atop SwingUtilities. 120 Listing 9.3. Simple Event Listener. 120 Figure 9.2. Control Flow with Separate Model and View Objects. 121 Listing 9.4. Binding a LongͲrunning Task to a Visual Component. 121 Listing 9.5. LongͲrunning Task with User Feedback. 122 Listing 9.6. Cancelling a LongͲrunning Task. 122 Listing 9.7. Background Task Class Supporting Cancellation, Completion Notification, and Progress Notification. 124 Listing 9.8. Initiating a LongͲrunning, Cancellable Task with BackgroundTask. 124 Chapter 10. Avoiding Liveness Hazards 128 Figure 10.1. Unlucky Timing in LeftRightDeadlock. 128 Listing 10.1. Simple LockͲordering Deadlock. Don't Do this. 129 Listing 10.2. Dynamic LockͲordering Deadlock. Don't Do this. 129 Listing 10.3. Inducing a Lock Ordering to Avoid Deadlock. 130 Listing 10.4. Driver Loop that Induces Deadlock Under Typical Conditions. 131 Listing 10.5. LockͲordering Deadlock Between Cooperating Objects. Don't Do this. 132 Listing 10.6. Using Open Calls to Avoiding Deadlock Between Cooperating Objects. 133 Listing 10.7. Portion of Thread Dump After Deadlock. 135 Chapter 11. Performance and Scalability 137 Figure 11.1. Maximum Utilization Under Amdahl's Law for Various Serialization Percentages. 140 Listing 11.1. Serialized Access to a Task Queue. 141 Figure 11.2. Comparing Queue Implementations. 141 Listing 11.2. Synchronization that has No Effect. Don't Do this. 142 Listing 11.3. Candidate for Lock Elision. 143 Listing 11.4. Holding a Lock Longer than Necessary. 145 Listing 11.5. Reducing Lock Duration. 145 Listing 11.6. Candidate for Lock Splitting. 146 Listing 11.7. ServerStatus Refactored to Use Split Locks. 146 Listing 11.8. HashͲbased Map Using Lock Striping. 148 Figure 11.3. Comparing Scalability of Map Implementations. 150 Chapter 12. Testing Concurrent Programs 153 Listing 12.1. Bounded Buffer Using Semaphore. 154
Java Concurrency In Practice Listing 12.2.Basic Unit Tests for BoundedBuffer. 154 Listing 12.3.Testing Blocking and Responsiveness to Interruption. 156 Listing 12.4.Medium-quality Random Number Generator Suitable for Testing. 157 Listing 12.5.Producer-consumer Test Program for BoundedBuffer. 158 Listing 12.6.Producer and Consumer Classes Used in PutTakeTest. 158 Listing 12.7.Testing for Resource Leaks. 159 Listing 12.8.Thread Factory for Testing ThreadPoolExecutor. 160 Listing 12.9.Test Method to Verify Thread Pool Expansion. 160 Listing 12.10.Using Thread.yield to Generate More Interleavings. 160 Listing 12.11.Barrier-based Timer. 161 Figure 12.1.TimedPutTakeTest with Various Buffer Capacities. 162 Listing 12.12.Testing with a Barrier-based Timer. 162 Listing 12.13.Driver Program-for TimedPutTakeTest. 163 Figure 12.2.Comparing Blocking Queue Implementations. 163 Figure 12.3.Completion Time Histogram for TimedPutTakeTest with Default (Non-fair)and Fair Semaphores. 164 Figure 12.4.Completion Time Histogram for TimedPutTakeTest with Single-item Buffers. 164 Figure 12.5.Results Biased by Dynamic Compilation. 165 Chapter 13-Explicit Locks 171 Listing 13.1.Lock Interface. 171 Listing 13.2.Guarding Object State Using ReentrantLock. 171 Listing 13.3.Avoiding Lock-ordering Deadlock Using trylock. 173 Listing 13.4.Locking with a Time Budget. 173 Listing 13.5.Interruptible Lock Acquisition. 173 Figure 13.1.Intrinsic Locking Versus ReentrantLock Performance on Java 5.0 and Java 6. 174 Figure 13.2.Fair Versus Non-fair Lock Performance 175 Listing 13.6.ReadwriteLock Interface. 176 Listing 13.7.Wrapping a Map with a Read-write Lock. 178 Figure 13.3.Read-write Lock Performance. 178 Chapter 14-Building Custom Synchronizers 179 Listing 14.1.Structure of Blocking State-dependent Actions. 179 Listing 14.2.Base Class for Bounded Buffer Implementations. 180 Listing 14.3.Bounded Buffer that Balks When Preconditions are Not Met. 180 Listing 14.4.Client Logic for Calling GrumpyBoundedBuffer 181 Figure 14.1.Thread Oversleeping Because the Condition Became True Just After It Went to Sleep. 181 Listing 14.5.Bounded Buffer Using Crude Blocking. 182
x Java Concurrency In Practice Listing 12.2. Basic Unit Tests for BoundedBuffer. 154 Listing 12.3. Testing Blocking and Responsiveness to Interruption. 156 Listing 12.4. MediumͲquality Random Number Generator Suitable for Testing. 157 Listing 12.5. ProducerͲconsumer Test Program for BoundedBuffer. 158 Listing 12.6. Producer and Consumer Classes Used in PutTakeTest. 158 Listing 12.7. Testing for Resource Leaks. 159 Listing 12.8. Thread Factory for Testing ThreadPoolExecutor. 160 Listing 12.9. Test Method to Verify Thread Pool Expansion. 160 Listing 12.10. Using Thread.yield to Generate More Interleavings. 160 Listing 12.11. BarrierͲbased Timer. 161 Figure 12.1. TimedPutTakeTest with Various Buffer Capacities. 162 Listing 12.12. Testing with a BarrierͲbased Timer. 162 Listing 12.13. Driver ProgramͲfor TimedPutTakeTest. 163 Figure 12.2. Comparing Blocking Queue Implementations. 163 Figure 12.3. Completion Time Histogram for TimedPutTakeTest with Default (NonͲfair) and Fair Semaphores. 164 Figure 12.4. Completion Time Histogram for TimedPutTakeTest with SingleͲitem Buffers. 164 Figure 12.5. Results Biased by Dynamic Compilation. 165 Chapter 13 - Explicit Locks 171 Listing 13.1. Lock Interface. 171 Listing 13.2. Guarding Object State Using ReentrantLock. 171 Listing 13.3. Avoiding LockͲordering Deadlock Using trylock. 173 Listing 13.4. Locking with a Time Budget. 173 Listing 13.5. Interruptible Lock Acquisition. 173 Figure 13.1. Intrinsic Locking Versus ReentrantLock Performance on Java 5.0 and Java 6. 174 Figure 13.2. Fair Versus NonͲfair Lock Performance. 175 Listing 13.6. ReadWriteLock Interface. 176 Listing 13.7. Wrapping a Map with a ReadͲwrite Lock. 178 Figure 13.3. ReadͲwrite Lock Performance. 178 Chapter 14 - Building Custom Synchronizers 179 Listing 14.1. Structure of Blocking StateͲdependent Actions. 179 Listing 14.2. Base Class for Bounded Buffer Implementations. 180 Listing 14.3. Bounded Buffer that Balks When Preconditions are Not Met. 180 Listing 14.4. Client Logic for Calling GrumpyBoundedBuffer. 181 Figure 14.1. Thread Oversleeping Because the Condition Became True Just After It Went to Sleep. 181 Listing 14.5. Bounded Buffer Using Crude Blocking. 182