KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > tests > lock > LockTest


1 package org.jboss.cache.tests.lock;
2
3 import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
4 import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore;
5 import EDU.oswego.cs.dl.util.concurrent.Sync;
6 import junit.framework.Test;
7 import junit.framework.TestCase;
8 import junit.framework.TestSuite;
9 import org.jboss.cache.lock.*;
10
11 /**
12  * Various tests that test isolation level semantics provided by locks
13  *
14  * @author Bela Ban
15  * @version $Id: LockTest.java,v 1.1.1.1 2005/03/31 10:15:09 belaban Exp $
16  */

17 public class LockTest extends TestCase {
18    int value=10;
19    Throwable JavaDoc t1_ex, t2_ex;
20    long start=0;
21    final long TIMEOUT=5000;
22    final long SLEEP=500;
23
24
25    public LockTest(String JavaDoc name) {
26       super(name);
27    }
28
29
30
31    public void tearDown() throws Exception JavaDoc {
32       super.tearDown();
33       t1_ex=t2_ex=null;
34    }
35
36
37    class MyFIFOSemaphore extends FIFOSemaphore {
38       public MyFIFOSemaphore(long l) {
39          super(l);
40       }
41
42       public void acquire() throws InterruptedException JavaDoc {
43          // log("acquiring sem (permits=" + permits() + ")");
44
super.acquire();
45          // log("acquired sem (permits=" + permits() + ")");
46
}
47
48       public void release() {
49          // log("releasing sem (permits=" + permits() + ")");
50
super.release();
51          // log("released sem (permits=" + permits() + ")");
52
}
53    }
54
55
56    /**
57     * Thread1 reads data, thread2 changes and - before thread2 commits - t1 should see t2's changes.
58     * Timeline:
59     * <ol>
60     * T1 reads data - 10
61     * T2 writes data - 20
62     * T1 reads data - 20 (see's T2's uncommitted modfication)
63     * T2 commits (releases its lock)
64     * T1 reads data - 20
65     * </ol>
66     */

67    public void testReadUncommitted() throws Throwable JavaDoc {
68       final LockStrategy s=new LockStrategyReadUncommitted();
69       final FIFOSemaphore sem=new MyFIFOSemaphore(1);
70       final CyclicBarrier barrier=new CyclicBarrier(2);
71
72       Thread JavaDoc t1=new Thread JavaDoc("t1") {
73          Sync lock=null;
74
75          public void run() {
76             try {
77                sem.acquire(); // we're first to the semaphore
78

79                // log("waiting on barrier");
80
barrier.barrier(); // wait until t2 joins us
81
// log("passed barrier");
82
lock=s.readLock();
83                lock.attempt(TIMEOUT);
84                log("1st read: value is " + value);
85                assertEquals(10, value);
86                sem.release(); // give t2 time to make the modification
87
_sleep(100);
88
89                sem.acquire(); // to read the uncommitted modification by t2
90
log("2nd read: value is " + value + "; we should see t2's uncommitted change (20)");
91                assertEquals(20, value); // we're seeing the modification by t2 before t2 committed (a.k.a. released the lock)
92
sem.release();
93                _sleep(100);
94
95                sem.acquire(); // to read the committed change by t2
96
log("3rd read: value is still " + value + "; we should see t2's committed change");
97                assertEquals(20, value);
98             }
99             catch(Throwable JavaDoc ex) {
100                t1_ex=ex;
101             }
102             finally {
103                if(lock != null)
104                   lock.release();
105                sem.release();
106             }
107          }
108       };
109
110
111       Thread JavaDoc t2=new Thread JavaDoc("t2") {
112          Sync lock=null;
113
114          public void run() {
115             try {
116                _sleep(100);
117                // log("waiting on barrier");
118
barrier.barrier();
119                // log("passed barrier");
120
sem.acquire();
121                lock=s.writeLock();
122                lock.attempt(TIMEOUT);
123                log("changing value from " + value + " to 20");
124                value=20;
125                sem.release(); // now t1 can read the uncommitted modification
126
_sleep(100);
127
128                sem.acquire(); // to release the lock
129
log("committing the TX");
130                lock.release();
131             }
132             catch(Throwable JavaDoc ex) {
133                t2_ex=ex;
134             }
135             finally {
136                if(lock != null)
137                   lock.release();
138                sem.release();
139             }
140          }
141       };
142
143       t1.start();
144       t2.start();
145       t1.join();
146       t2.join();
147       if(t1_ex != null)
148          throw t1_ex;
149       if(t2_ex != null)
150          throw t2_ex;
151    }
152
153
154
155    /**
156     * Thread1 reads data, thread2 changes and - before thread2 commits - t1 should *not* see t2's changes.
157     * Timeline:
158     * <ol>
159     * T1 reads data - 10
160     * T2 writes data - 20 (*not* visible to T1)
161     * T1 reads data - 10 (should *not* see T2's uncommitted modfication)
162     * T2 commits (releases its lock)
163     * T1 sees T2's committed modification - 20
164     * </ol>
165     * <em>Commented for now, until we get the right semantics</em>
166     */

167 // public void testReadCommitted() throws Throwable {
168
// final LockStrategy s=new LockStrategyReadCommitted();
169
//
170
// Thread t1=new Thread("t1") {
171
// Sync lock=null;
172
//
173
// public void run() {
174
// try {
175
// lock=s.readLock();
176
// lock.attempt(TIMEOUT);
177
// log("1st read: value is " + value);
178
// assertEquals(10, value);
179
// _sleep(SLEEP);
180
//
181
// log("2nd read: value is " + value + "; we should *not* see t2's uncommitted change (20)");
182
// assertEquals(10, value); // we're seeing the modification by t2 before t2 committed (a.k.a. released the lock)
183
// _sleep(SLEEP);
184
//
185
// log("3rd read: value is still " + value + "; we should see t2's committed change");
186
// assertEquals(20, value);
187
// }
188
// catch(Throwable ex) {
189
// t1_ex=ex;
190
// }
191
// finally {
192
// lock.release();
193
// }
194
// }
195
// };
196
//
197
//
198
// Thread t2=new Thread("t2") {
199
// Sync lock=null;
200
//
201
// public void run() {
202
// try {
203
// _sleep(100);
204
// lock=s.writeLock();
205
// lock.attempt(TIMEOUT);
206
// log("changing value from " + value + " to 20");
207
// value=20;
208
// _sleep(SLEEP);
209
//
210
// log("committing the TX");
211
// lock.release();
212
// }
213
// catch(Throwable ex) {
214
// t2_ex=ex;
215
// }
216
// finally {
217
// lock.release();
218
// }
219
// }
220
// };
221
//
222
// t1.start();
223
// t2.start();
224
// t1.join();
225
// t2.join();
226
// if(t1_ex != null)
227
// throw t1_ex;
228
// if(t2_ex != null)
229
// throw t2_ex;
230
// }
231

232
233
234    public void testWriteThanRead() throws Throwable JavaDoc {
235        final LockStrategy s=new LockStrategyReadCommitted();
236
237        Thread JavaDoc t1=new Thread JavaDoc("t1") {
238           Sync lock=null;
239
240           public void run() {
241              try {
242                 _sleep(100);
243                 lock=s.readLock();
244                 lock.attempt(TIMEOUT);
245                 log("1st read: value is " + value);
246                 assertEquals(20, value);
247                 _sleep(SLEEP);
248
249                 log("2nd read: value is " + value + "; we should see t2's uncommitted change (20)");
250                 assertEquals(20, value); // we're seeing the modification by t2 before t2 committed (a.k.a. released the lock)
251
_sleep(SLEEP);
252              }
253              catch(Throwable JavaDoc ex) {
254                 t1_ex=ex;
255              }
256              finally {
257                 lock.release();
258              }
259           }
260        };
261
262
263        Thread JavaDoc t2=new Thread JavaDoc("t2") {
264           Sync lock=null;
265
266           public void run() {
267              try {
268                 lock=s.writeLock();
269                 lock.attempt(TIMEOUT);
270                 log("changing value from " + value + " to 20");
271                 value=20;
272                 _sleep(SLEEP);
273
274                 log("committing the TX");
275                 lock.release();
276              }
277              catch(Throwable JavaDoc ex) {
278                 t2_ex=ex;
279              }
280              finally {
281                 lock.release();
282              }
283           }
284        };
285
286        t2.start();
287        t1.start();
288        t2.join();
289        t1.join();
290        if(t1_ex != null)
291           throw t1_ex;
292        if(t2_ex != null)
293           throw t2_ex;
294     }
295
296
297
298
299    /**
300     * Thread1 reads data, thread2 changes and - before thread2 commits - t1 should *not* see t2's changes.
301     * In addition, Thread1 should *not* see thread2's changes even after thread2 commits, until thread1 commits.
302     * Timeline:
303     * <ol>
304     * T1 reads data - 10
305     * T2 writes data - 20 (*not* visible to T1)
306     * T1 reads data - 10 (should *not* see T2's uncommitted modfication)
307     * T2 commits (releases its lock)
308     * T1 reads data, should *not* see T2's committed modification - 10
309     * T1 commits
310     * T1 starts a new TX - should see 20
311     * </ol>
312     * Note: because we use pessimistic locking, the above sequence will effectively be serialized into sequential
313     * execution: thread1 will acquire the read lock on the data and hold on to it until TX commit, only then will
314     * thread2 be able to access the data with a write lock.
315     */

316    public void testRepeatableRead() throws Throwable JavaDoc {
317       final LockStrategy s=new LockStrategyRepeatableRead();
318
319       Thread JavaDoc t1=new Thread JavaDoc("t1") {
320          Sync lock=null;
321
322          public void run() {
323             try {
324                lock=s.readLock();
325                lock.attempt(TIMEOUT);
326                log("1st read: value is " + value);
327                assertEquals(10, value);
328                _sleep(SLEEP);
329
330                log("2nd read: value is " + value + "; we should *not* see t2's uncommitted change (20)");
331                assertEquals(10, value);
332                _sleep(SLEEP);
333
334                log("3rd read: value is still " + value + "; we should not see t2's committed change");
335                assertEquals(10, value);
336                lock.release();
337
338                _sleep(SLEEP);
339                lock.attempt(TIMEOUT);
340                log("4th read: value is now " + value + "; we should see t2's committed change in our new TX");
341                assertEquals(20, value);
342             }
343             catch(Throwable JavaDoc ex) {
344                t1_ex=ex;
345             }
346             finally {
347                lock.release();
348             }
349          }
350       };
351
352
353       Thread JavaDoc t2=new Thread JavaDoc("t2") {
354          Sync lock=null;
355
356          public void run() {
357             try {
358                _sleep(100);
359                lock=s.writeLock();
360                lock.attempt(TIMEOUT);
361                log("changing value from " + value + " to 20");
362                value=20;
363                _sleep(SLEEP);
364
365                log("committing the TX");
366                lock.release();
367             }
368             catch(Throwable JavaDoc ex) {
369                t2_ex=ex;
370             }
371             finally {
372                lock.release();
373             }
374          }
375       };
376
377       t1.start();
378       t2.start();
379       t1.join();
380       t2.join();
381       if(t1_ex != null)
382          throw t1_ex;
383       if(t2_ex != null)
384          throw t2_ex;
385    }
386
387
388    /**
389     * Because only 1 reader or writer can hold the lock at any given time, since thread1 is the first to get the lock,
390     * it will hold on to it until it commits. The the writer thread (thread2) will have a chance to change the value.
391     * Timeline:
392     * <ol>
393     * T1 reads data - 10
394     * T1 commits
395     * T2 writes data - 20
396     * T2 commits
397     * T1 starts a new TX and reads data - 20
398     * T2 commits (releases its lock)
399     * </ol>
400     */

401    public void testSerializable() throws Throwable JavaDoc {
402       final LockStrategy s=new LockStrategySerializable();
403
404       Thread JavaDoc t1=new Thread JavaDoc("t1") {
405          Sync lock=null;
406
407          public void run() {
408             try {
409                lock=s.readLock();
410                lock.attempt(TIMEOUT);
411                log("1st read: value is " + value);
412                assertEquals(10, value);
413                lock.release();
414                _sleep(SLEEP);
415
416                lock.attempt(TIMEOUT);
417                log("2nd read: value is " + value + "; we should see t2's committed change (20)");
418                assertEquals(20, value);
419             }
420             catch(Throwable JavaDoc ex) {
421                t1_ex=ex;
422             }
423             finally {
424                lock.release();
425             }
426          }
427       };
428
429
430       Thread JavaDoc t2=new Thread JavaDoc("t2") {
431          Sync lock=null;
432
433          public void run() {
434             try {
435                _sleep(100);
436                lock=s.writeLock();
437                lock.attempt(TIMEOUT);
438                log("changing value from " + value + " to 20");
439                value=20;
440                log("committing the TX");
441                lock.release();
442             }
443             catch(Throwable JavaDoc ex) {
444                t2_ex=ex;
445             }
446             finally {
447                lock.release();
448             }
449          }
450       };
451
452       t1.start();
453       t2.start();
454       t1.join();
455       t2.join();
456       if(t1_ex != null)
457          throw t1_ex;
458       if(t2_ex != null)
459          throw t2_ex;
460    }
461
462
463
464    void _sleep(long time) {
465       Thread.yield();
466       try {Thread.sleep(time);} catch(InterruptedException JavaDoc e) {}
467    }
468
469
470    void log(String JavaDoc s) {
471       long now;
472       if(start == 0)
473          start=System.currentTimeMillis();
474       now=System.currentTimeMillis();
475
476       System.out.println("[" + Thread.currentThread().getName() + "] [" + (now - start) + "] " + s);
477     }
478
479
480    public static void main(String JavaDoc[] args) throws Exception JavaDoc {
481       junit.textui.TestRunner.run(suite());
482    }
483
484    // Needed for JUnit.
485
public static Test suite() {
486       TestSuite suite=new TestSuite();
487       suite.addTestSuite(LockTest.class);
488       return suite;
489    }
490
491
492
493
494 }
495
496
Popular Tags