KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > concurrent > test > ReadWriteLockTestCase


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.concurrent.test;
9
10 import junit.framework.TestCase;
11 import org.apache.avalon.excalibur.concurrent.ReadWriteLock;
12
13 /**
14  * Test harness for the ReadWriteLock.
15  *
16  * @author <a HREF="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
17  */

18 public class ReadWriteLockTestCase
19     extends TestCase
20 {
21     /**
22      * Worker thread that attempts to
23      * aquire a write lock. Start it, wait a little while
24      * and call the hasSuccess() method.
25      */

26     static class TriesWriteLock
27         extends Thread JavaDoc
28     {
29         protected ReadWriteLock m_lock;
30         protected boolean m_success = false;
31
32         public TriesWriteLock(ReadWriteLock lock)
33         {
34             m_lock = lock;
35         }
36
37         public boolean hasSuccess()
38         {
39             return m_success;
40         }
41
42         public void run ()
43         {
44             try
45             {
46                 m_lock.aquireWrite();
47                 m_success = true;
48             }
49             catch (Exception JavaDoc e)
50             {
51                 // Ignore. Errors are handled by the testlet
52
// monitoring hasSuccess().
53
}
54         }
55     }
56
57     /**
58      * Worker thread that attempts to
59      * aquire a read lock. Start it, wait a little while
60      * and call the hasSuccess() method.
61      */

62     static class TriesReadLock
63         extends Thread JavaDoc
64     {
65         protected ReadWriteLock m_lock;
66         protected boolean m_success = false;
67
68         public TriesReadLock( final ReadWriteLock lock )
69         {
70             m_lock = lock;
71         }
72
73         public boolean hasSuccess()
74         {
75             return m_success;
76         }
77
78         public void run ()
79         {
80             try
81             {
82                 m_lock.aquireRead();
83                 m_success = true;
84             }
85             catch( final Exception JavaDoc e )
86             {
87                 // Ignore. Errors are handled by the testlet
88
// monitoring hasSuccess().
89
}
90         }
91     }
92
93     public ReadWriteLockTestCase (String JavaDoc name) {
94         super (name);
95     }
96
97     /**
98      * Attempt to aquire and release read and write locks from
99      * different threads.
100      */

101     public void testRWLock()
102         throws Exception JavaDoc
103     {
104         final ReadWriteLock lock = new ReadWriteLock();
105         final TriesWriteLock wl = new TriesWriteLock( lock );
106         final TriesReadLock rl = new TriesReadLock( lock );
107
108         rl.start ();
109         Thread.currentThread().sleep( 100 );
110         assertTrue( "Attempted to aquire read lock.", rl.hasSuccess () );
111
112         wl.start ();
113         Thread.currentThread().sleep( 100 );
114         assertTrue( "Attempted to aquire write lock.", !wl.hasSuccess () );
115
116         lock.release();
117
118         Thread.currentThread().sleep( 100 );
119         assertTrue( "Attempted to aquire write lock after releasing read lock.",
120                     wl.hasSuccess () );
121
122         lock.release();
123
124         //
125
// And see that the write lock is released properly.
126
//
127
final TriesReadLock r2 = new TriesReadLock( lock );
128         r2.start ();
129         Thread.currentThread().sleep( 100 );
130         assertTrue( "Attempted to aquire read lock.", r2.hasSuccess () );
131
132         lock.release();
133     }
134
135     /**
136      * Test that the lock throws an IllegalStateException when
137      * one attempts to release an already released lock.
138      */

139     public void testIllegalState () throws Exception JavaDoc
140     {
141         ReadWriteLock lock = new ReadWriteLock();
142         try
143         {
144             lock.release();
145             fail( "ReadWriteLock did *not* signal illegal state when an attempt was made to release an unlocked lock." );
146         }
147         catch (IllegalStateException JavaDoc ise)
148         {
149             // OK, we should receive this one.
150
}
151     }
152
153     /**
154      * Tests that attempts to aquire a write lock
155      * are given higher priority than attempts
156      * at aquiring a read lock.
157      */

158     public void testMultipleWriters () throws Exception JavaDoc
159     {
160         ReadWriteLock lock = new ReadWriteLock();
161         TriesReadLock rla = new TriesReadLock( lock );
162         TriesReadLock rlb = new TriesReadLock( lock );
163         TriesWriteLock wla = new TriesWriteLock( lock );
164         TriesWriteLock wlb = new TriesWriteLock( lock );
165
166         rla.start ();
167         Thread.currentThread().sleep( 100 );
168         assertTrue( "Attempted to aquire read lock.", rla.hasSuccess () );
169
170         wla.start ();
171         wlb.start ();
172
173         //
174
// Give the write lock threads some time to attempt
175
// to aquire a lock.
176
//
177
Thread.currentThread().sleep( 100 );
178
179         rlb.start ();
180         Thread.currentThread().sleep( 100 );
181
182         //
183
// Two write locks queued up, one read lock queued up.
184
//
185
// rla holds read lock
186
// wlb, wla -> (read lock is held)
187
// rlb -> (has waiting write locks)
188
//
189
assertTrue( "Attempted to aquire write lock, and succeeded even though it shouldn't be possible (rla has the lock).",
190                     !wla.hasSuccess() && !wlb.hasSuccess() && !rlb.hasSuccess() );
191
192         //
193
// Upon releasing the lock, the write lock attempt should succeed, while the read
194
// lock should still be waiting.
195
//
196
lock.release();
197         Thread.currentThread().sleep( 100 );
198
199         //
200
// One write lock queued up, one read lock queued up.
201
//
202
// wla or wlb holds write lock
203
// wlb || wla -> (write lock is held)
204
// rlb -> (has waiting write lock)
205
//
206
assertTrue( "Attempted to aquire write lock after releasing read lock.",
207                     (wla.hasSuccess () || wlb.hasSuccess () ) && !rlb.hasSuccess ()
208                    && !(wla.hasSuccess () && wlb.hasSuccess () ));
209
210         //
211
// Release write lock again. The other one of wla and wlb should grab the lock.
212
//
213
lock.release();
214         Thread.currentThread().sleep( 100 );
215
216         //
217
// Two write locks queued up, one read lock queued up.
218
//
219
// wla or wlb holds write lock
220
// rlb -> (write lock is held)
221
//
222
assertTrue( "Attempted to aquire write lock after releasing read lock.",
223                     wla.hasSuccess () && wlb.hasSuccess () && !rlb.hasSuccess () );
224
225         //
226
// Release the lock - the waiting read lock should grab it.
227
//
228
lock.release();
229         Thread.currentThread().sleep( 100 );
230         assertTrue( "Attempted to aquire write lock after releasing read lock.",
231                     wla.hasSuccess () && wlb.hasSuccess () && rlb.hasSuccess () );
232     }
233
234     /**
235      * Tests that the lock behaves correctly when
236      * multiple read locks are obtained.
237      */

238     public void testMultipleReaders () throws Exception JavaDoc
239     {
240         ReadWriteLock lock = new ReadWriteLock();
241         TriesReadLock rla = new TriesReadLock( lock );
242         TriesReadLock rlb = new TriesReadLock( lock );
243         TriesWriteLock wla = new TriesWriteLock( lock );
244
245         rla.start ();
246         rlb.start ();
247         Thread.currentThread().sleep( 100 );
248         assertTrue( "Attempted to aquire read multiple read locks.",
249                     rla.hasSuccess () && rlb.hasSuccess () );
250
251         wla.start ();
252         Thread.currentThread().sleep( 100 );
253         assertTrue( "Write lock aquired even though read locks are held.", !wla.hasSuccess () );
254
255         lock.release ();
256         Thread.currentThread().sleep( 100 );
257         assertTrue( "Write lock aquired even though read locks are held. (There should be one read lock left)",
258                     !wla.hasSuccess () );
259
260         lock.release ();
261         Thread.currentThread().sleep( 100 );
262         assertTrue( "Write lock not aquired even though lock should be released.",
263                     wla.hasSuccess () );
264     }
265
266     /**
267      * Tests the tryAquireXXX methods.
268      */

269     public void testTrying () throws Exception JavaDoc
270     {
271         ReadWriteLock lock = new ReadWriteLock();
272         TriesReadLock rla = new TriesReadLock( lock );
273         TriesReadLock rlb = new TriesReadLock( lock );
274         TriesWriteLock wla = new TriesWriteLock( lock );
275         TriesWriteLock wlb = new TriesWriteLock( lock );
276
277         //
278
// Grab a read lock, try to aquire one more (should work),
279
// and try aquiring a write lock (should not work).
280
//
281
rla.start ();
282         Thread.currentThread().sleep( 100 );
283         assertTrue( "Could not aquire a read lock.", rla.hasSuccess() );
284
285         assertTrue( "Could not aquire a read lock, even though only a read lock is held.",
286                     lock.tryAquireRead() );
287
288         assertTrue( "Could aquire a write lock.", !lock.tryAquireWrite() );
289
290         //
291
// Release both locks.
292
//
293
lock.release();
294         lock.release();
295
296         //
297
// Try aquiring a write lock (should work), a read
298
// lock (should fail) and another write lock (should fail).
299
//
300
assertTrue( "Could not aquire a write lock.", lock.tryAquireWrite() );
301         assertTrue( "Could aquire a read lock.", !lock.tryAquireRead() );
302         assertTrue( "Could aquire a write lock.", !lock.tryAquireWrite() );
303
304         //
305
// Release the write lock.
306
//
307
lock.release();
308
309         assertTrue( "Could not aquire a write lock after releasing the lock.",
310                     lock.tryAquireWrite() );
311     }
312
313     /**
314      * Tests a condition pointed out to me (L.Sutic) by Avi Drissman
315      * <a HREF="drissman@acm.org">drissman@acm.org</a>. If you hold
316      * a read lock, and a thread waiting for a write lock is interrupted,
317      * there is no way to aquire a read lock again.
318      *
319      * (This condition is fixed, 2001-10-31.)
320      */

321     public void testDeadLock () throws Exception JavaDoc {
322         ReadWriteLock lock = new ReadWriteLock();
323         TriesReadLock rla = new TriesReadLock( lock );
324         TriesReadLock rlb = new TriesReadLock( lock );
325         TriesWriteLock wla = new TriesWriteLock( lock );
326         TriesWriteLock wlb = new TriesWriteLock( lock );
327
328         //
329
// Grab a read lock.
330
//
331
rla.start();
332         Thread.currentThread().sleep( 100 );
333         assertTrue( rla.hasSuccess() );
334
335         //
336
// Try to grab a write lock. (The attempt stalls,
337
// because we are holding a read lock.)
338
//
339
wla.start();
340         Thread.currentThread().sleep( 100 );
341         assertTrue( !wla.hasSuccess() );
342
343         //
344
// Interupt the thread waiting for the write lock...
345
//
346
wla.interrupt();
347
348         //
349
// ...and release the read lock.
350
//
351
lock.release();
352
353         //
354
// Right, we are in the condition described by Drissman.
355
// Now try to aquire, in turn, a read and a write lock.
356
// Before the fix, the assertion immediately below
357
// would fail.
358
//
359
rlb.start();
360         Thread.currentThread().sleep( 100 );
361         assertTrue( rlb.hasSuccess() );
362         lock.release();
363
364         wlb.start();
365         Thread.currentThread().sleep( 100 );
366         assertTrue( wlb.hasSuccess() );
367         lock.release();
368      }
369 }
370
371
372
Popular Tags