2 * Copyright 2005 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.concurrency;
18 import java.util.HashSet;
21 * Read-write lock for allowing multiple concurrent readers or at most one
22 * writer. This implementation does not aim for high performance but for
23 * robustness and simplicity. Users of this class should not synchronize on
24 * objects of this class.
26 public class ReadWriteLock {
28 * Sets containing the references to the threads that are currently reading.
29 * This administration is useful to check that the lock has already been
30 * acquired before it is release. This check adds robustness to the
33 private HashSet<Thread> readers;
36 * The thread that has acquired the lock for writing or null if no such
37 * thread exists currently.
39 private Thread writer;
42 * Constructs read-write lock.
44 public ReadWriteLock() {
45 readers = new HashSet<Thread>();
50 * Acquires the lock for reading. This call will block until the lock can be
53 * @throws IllegalStateException
54 * Thrown if the read or write lock is already acquired.
56 public synchronized void acquireRead() {
57 if (readers.contains(Thread.currentThread())) {
58 throw new IllegalStateException(
59 "Read lock already acquired by current thread: " +
60 Thread.currentThread());
63 if (writer == Thread.currentThread()) {
64 throw new IllegalStateException(
65 "Trying to acquire the read lock while already holding a write lock: " +
66 Thread.currentThread());
69 while (writer != null) {
72 } catch (InterruptedException e) {
77 readers.add(Thread.currentThread());
81 * Releases the lock for reading. Note: This implementation assumes that the
82 * lock has already been acquired for reading previously.
84 * @throws IllegalStateException
85 * Thrown when the lock was not acquired by this thread.
87 public synchronized void releaseRead() {
88 if (!readers.remove(Thread.currentThread())) {
89 throw new IllegalStateException(
90 "Cannot release read lock because current thread has not acquired it.");
93 if (readers.size() == 0) {
99 * Acquires the lock for writing. This call will block until the lock has
102 * @throws IllegalStateException
103 * Thrown if the read or write lock is already acquired.
105 public synchronized void acquireWrite() {
106 if (writer == Thread.currentThread()) {
107 throw new IllegalStateException(
108 "Trying to acquire a write lock while already holding the write lock: " +
109 Thread.currentThread());
112 if (readers.contains(Thread.currentThread())) {
113 throw new IllegalStateException(
114 "Trying to acquire a write lock while already holding the read lock: " +
115 Thread.currentThread());
118 // wait until there are no more writers and no more
120 while ((writer != null) || (readers.size() > 0)) {
123 } catch (InterruptedException e) {
128 writer = Thread.currentThread();
130 // notification not necessary since all writers and
131 // readers are now blocked by this thread.
135 * Releases the lock for writing.
137 * @throws IllegalStateException
138 * Thrown when the lock was not acquired.
140 public synchronized void releaseWrite() {
141 if (writer != Thread.currentThread()) {
142 throw new IllegalStateException(
143 "Cannot release write lock because it was not acquired. ");