Code - Class EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock


1 /*
2   File: FIFOReadWriteLock.java
3
4   Originally written by Doug Lea and released into the public domain.
5   This may be used for any purposes whatsoever without acknowledgment.
6   Thanks for the assistance and support of Sun Microsystems Labs,
7   and everyone contributing, testing, and using this code.
8
9   History:
10   Date Who What
11   11Jun1998 dl Create public version
12   23nov2001 dl Replace main algorithm with fairer
13                               version based on one by Alexander Terekhov
14 */

15
16 package EDU.oswego.cs.dl.util.concurrent;
17
18
19 /**
20  * This class implements a policy for reader/writer locks in which
21  * threads contend in a First-in/First-out manner for access (modulo
22  * the limitations of FIFOSemaphore, which is used for queuing). This
23  * policy does not particularly favor readers or writers. As a
24  * byproduct of the FIFO policy, the <tt>attempt</tt> methods may
25  * return <tt>false</tt> even when the lock might logically be
26  * available, but, due to contention, cannot be accessed within the
27  * given time bound. <p>
28  *
29  * This lock is <em>NOT</em> reentrant. Current readers and
30  * writers should not try to re-obtain locks while holding them.
31  * <p>
32  *
33  * [<a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] <p>
34  *
35  * @see FIFOSemaphore
36 **/

37
38 public class FIFOReadWriteLock implements ReadWriteLock {
39
40   /**
41    * Fair Semaphore serving as a kind of mutual exclusion lock.
42    * Writers acquire on entry, and hold until rwlock exit.
43    * Readers acquire and release only during entry (but are
44    * blocked from doing so if there is an active writer).
45    **/

46   protected final FIFOSemaphore entryLock = new FIFOSemaphore(1);
47
48   /**
49    * Number of threads that have entered read lock. Note that this is
50    * never reset to zero. Incremented only during acquisition of read
51    * lock while the "entryLock" is held, but read elsewhere, so is
52    * declared volatile.
53    **/

54   protected volatile int readers;
55
56   /**
57    * Number of threads that have exited read lock. Note that this is
58    * never reset to zero. Accessed only in code protected by
59    * synchronized(this). When exreaders != readers, the rwlock is
60    * being used for reading. Else if the entry lock is held, it is
61    * being used for writing (or in transition). Else it is free.
62    * Note: To distinguish these states, we assume that fewer than 2^32
63    * reader threads can simultaneously execute.
64    **/

65   protected int exreaders;
66
67   protected void acquireRead() throws InterruptedException {
68     entryLock.acquire();
69     ++readers;
70     entryLock.release();
71   }
72
73   protected synchronized void releaseRead() {
74     /*
75       If this is the last reader, notify a possibly waiting writer.
76       Because waits occur only when entry lock is held, at most one
77       writer can be waiting for this notification. Because increments
78       to "readers" aren't protected by "this" lock, the notification
79       may be spurious (when an incoming reader in in the process of
80       updating the field), but at the point tested in acquiring write
81       lock, both locks will be held, thus avoiding false alarms. And
82       we will never miss an opportunity to send a notification when it
83       is actually needed.
84     */

85
86     if (++exreaders == readers)
87       notify();
88   }
89
90   protected void acquireWrite() throws InterruptedException {
91     // Acquiring entryLock first forces subsequent entering readers
92
// (as well as writers) to block.
93
entryLock.acquire();
94     
95     // Only read "readers" once now before loop. We know it won't
96
// change because we hold the entry lock needed to update it.
97
int r = readers;
98     
99     try {
100       synchronized(this) {
101         while (exreaders != r)
102           wait();
103       }
104     }
105     catch (InterruptedException ie) {
106       entryLock.release();
107       throw ie;
108     }
109   }
110
111   protected void releaseWrite() {
112     entryLock.release();
113   }
114
115   protected boolean attemptRead(long msecs) throws InterruptedException {
116     if (!entryLock.attempt(msecs))
117       return false;
118
119     ++readers;
120     entryLock.release();
121     return true;
122   }
123
124   protected boolean attemptWrite(long msecs) throws InterruptedException {
125     long startTime = (msecs <= 0)? 0 : System.currentTimeMillis();
126
127     if (!entryLock.attempt(msecs))
128       return false;
129
130     int r = readers;
131
132     try {
133       synchronized(this) {
134         while (exreaders != r) {
135           long timeLeft = (msecs <= 0)? 0:
136             msecs - (System.currentTimeMillis() - startTime);
137           
138           if (timeLeft <= 0) {
139             entryLock.release();
140             return false;
141           }
142           
143           wait(timeLeft);
144         }
145         return true;
146       }
147     }
148     catch (InterruptedException ie) {
149       entryLock.release();
150       throw ie;
151     }
152   }
153
154   // support for ReadWriteLock interface
155

156   protected class ReaderSync implements Sync {
157     public void acquire() throws InterruptedException {
158       acquireRead();
159     }
160     public void release() {
161       releaseRead();
162     }
163     public boolean attempt(long msecs) throws InterruptedException {
164       return attemptRead(msecs);
165     }
166   }
167
168   protected class WriterSync implements Sync {
169     public void acquire() throws InterruptedException {
170       acquireWrite();
171     }
172     public void release() {
173       releaseWrite();
174     }
175     public boolean attempt(long msecs) throws InterruptedException {
176       return attemptWrite(msecs);
177     }
178   }
179
180   protected final Sync readerSync = new ReaderSync();
181   protected final Sync writerSync = new WriterSync();
182
183   public Sync writeLock() { return writerSync; }
184   public Sync readLock() { return readerSync; }
185
186 }
187

Java API By Example, From Geeks To Geeks. | Conditions of Use | About Us © 2002 - 2005, KickJava.com, or its affiliates