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;
22 * Read-write lock for allowing multiple concurrent readers or at most one
23 * writer. This implementation does not aim for high performance but for
24 * robustness and simplicity. Users of this class should not synchronize on
25 * objects of this class.
27 public class ReadWriteLock {
29 * Sets containing the references to the threads that are currently
30 * reading. This administration is useful to check that the lock has
31 * already been acquired before it is release. This check adds robustness
34 private HashSet<Thread> _readers;
37 * The thread that has acquired the lock for writing or null if no such
38 * thread exists currently.
40 private Thread _writer;
43 * Constructs read-write lock.
45 public ReadWriteLock() {
46 _readers = new HashSet<Thread>();
51 * Acquires the lock for reading. This call will block until the lock can
54 * @throws IllegalStateException Thrown if the read or write lock is
57 public synchronized void acquireRead() {
58 if (_readers.contains(Thread.currentThread())) {
59 throw new IllegalStateException(
60 "Read lock already acquired by current thread: "
61 + Thread.currentThread());
64 if (_writer == Thread.currentThread()) {
65 throw new IllegalStateException(
66 "Trying to acquire the read lock while already holding a write lock: "
67 + Thread.currentThread());
70 while (_writer != null) {
73 } catch (InterruptedException e) {
78 _readers.add(Thread.currentThread());
82 * Releases the lock for reading. Note: This implementation assumes that
83 * the lock has already been acquired for reading previously.
85 * @throws IllegalStateException Thrown when the lock was not acquired by
88 public synchronized void releaseRead() {
89 if (!_readers.remove(Thread.currentThread())) {
90 throw new IllegalStateException(
91 "Cannot release read lock because current thread has not acquired it.");
94 if (_readers.size() == 0) {
100 * Acquires the lock for writing. This call will block until the lock has
103 * @throws IllegalStateException Thrown if the read or write lock is
106 public synchronized void acquireWrite() {
107 if (_writer == Thread.currentThread()) {
108 throw new IllegalStateException(
109 "Trying to acquire a write lock while already holding the write lock: "
110 + Thread.currentThread());
113 if (_readers.contains(Thread.currentThread())) {
114 throw new IllegalStateException(
115 "Trying to acquire a write lock while already holding the read lock: "
116 + Thread.currentThread());
119 // wait until there are no more writers and no more
121 while ((_writer != null) || (_readers.size() > 0)) {
124 } catch (InterruptedException e) {
129 _writer = Thread.currentThread();
131 // notification not necessary since all writers and
132 // readers are now blocked by this thread.
136 * Releases the lock for writing.
138 * @throws IllegalStateException 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. ");