KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.jboss.cache.tests.lock;
2
3 import EDU.oswego.cs.dl.util.concurrent.Sync;
4 import junit.framework.Test;
5 import junit.framework.TestCase;
6 import junit.framework.TestSuite;
7 import org.jboss.cache.lock.ReadWriteLockWithUpgrade;
8
9 import java.io.FileWriter JavaDoc;
10 import java.io.IOException JavaDoc;
11 import java.io.Writer JavaDoc;
12 import java.util.Vector JavaDoc;
13
14 /**
15  * NonBlockingWriterLock is a read/write lock (with upgrade) that has
16  * non-blocking write lock acquisition on existing read lock(s).
17  * <p>Note that the write lock is exclusive among write locks, e.g.,
18  * only one write lock can be granted at one time, but the write lock
19  * is independent of the read locks. For example,
20  * a read lock to be acquired will be blocked if there is existing write lock, but
21  * will not be blocked if there are mutiple read locks already granted to other
22  * owners. On the other hand, a write lock can be acquired as long as there
23  * is no existing write lock, regardless how many read locks have been
24  * granted.
25  *
26  * @author <a HREF="mailto:cavin_song@yahoo.com">Cavin Song</a> April 22, 2004
27  * @version 1.0
28  */

29 public class ReadWriteLockWithUpgradeTest extends TestCase
30 {
31    static final ReadWriteLockWithUpgrade lock_ = new ReadWriteLockWithUpgrade();
32    static long SLEEP_MSECS = 500;
33    Vector JavaDoc lockResult = new Vector JavaDoc();
34    int NO_MORE_OP = 0;
35    int INVOKE_READ = 1;
36    int INVOKE_WRITE = 2;
37    int INVOKE_UPGRADE = 3;
38
39    public ReadWriteLockWithUpgradeTest(String JavaDoc name)
40    {
41       super(name);
42    }
43
44
45    public static void main(String JavaDoc[] args) throws Exception JavaDoc
46    {
47       log("\nBeginning ReadWriteLockWithUpgrade automated testing ...\n");
48
49       junit.textui.TestRunner.run(suite());
50    }
51
52    // Needed for JUnit.
53
public static Test suite()
54    {
55       TestSuite suite = new TestSuite();
56       // Adding test cases here ...
57
suite.addTestSuite(ReadWriteLockWithUpgradeTest.class);
58       return suite;
59    }
60
61    public void setUp()
62    {
63       logX("\n");
64       log("Setting up test case ...");
65    }
66
67    public void tearDown()
68    {
69       log("Tearing down test case ...");
70    }
71
72    public static void _sleep(long msecs)
73    {
74       try {
75          Thread.sleep(msecs);
76       } catch (InterruptedException JavaDoc ex) {
77       }
78    }
79
80    public static void log(String JavaDoc str)
81    {
82       System.out.println(Thread.currentThread() + ": "
83             + java.util.Calendar.getInstance().getTime() + " : " + str);
84    }
85
86    // For debugging purpose
87
public static void logX(String JavaDoc str)
88    {
89       log(str);
90 // try {
91
// logToFile(str);
92
// } catch (IOException ioe) {
93
// }
94
}
95
96    // Debugging intrnal function
97
public static void logToFile(String JavaDoc str) throws IOException JavaDoc
98    {
99       Writer JavaDoc out = new FileWriter JavaDoc("./RepeatableLogs.txt", true/*append*/);
100       out.write(str);
101       out.close();
102    }
103
104    /***************************************************************/
105    /* Utility functions to creat threads for RL, WL and UL */
106    /***************************************************************/
107    /**
108     * Creates a new thread and acquires a read lock with a timeout
109     * value specified by the caller. Optionally, the caller can request
110     * a second read or write lock after the first read lock request.
111     * The locking result is stored in a vector with the following
112     * format:
113     * <p><DL>
114     * <DD>'case number'-'thread name'-[RL|WL|UL]-[0|1]
115     * </DL>
116     * <p>where:
117     * <DL>
118     * <DD> 'case number' is the passed in test case # by the caller.
119     * <DD> 'thread name' is the passed in thread name by the caller.
120     * <DD> RL - indicating was doing read lock request.
121     * <DD> WL - indicating was doing write lock request.
122     * <DD> UL - indicating was doing upgrade lock request.
123     * <DD> 0 - indicating the locking request failed.
124     * <DD> 1 - indicating the locking request succeeded.
125     * </DL>
126     * <p>
127     * After all threads in each test case terminate, the test case
128     * should make the following call to verify the test result:
129     * <DL>
130     * <DD> asssertTrue(checkLockingResult(expected-result-string);
131     * </DL>
132     * <p>
133     * 'expected-result-string' is the locking result string
134     * described above. For example, "8-t1-RL-0" means that thread
135     * t1 in test case #8 doing a Read Lock request expects the
136     * operation to fail. If the expected result string can't be
137     * found then the test case is considered FAILED (ie, either
138     * the read lock request was successful or did not complete).
139     * <p>
140     * Each test case should also call cleanLockingResult() to reset
141     * result vector for the next test cases.
142     * @param caseNum Arbitrary string for the test case number.
143     * @param name Arbitrary string for the calling thread name.
144     * @param msecs Milliseconds that the thread should sleep after
145     * acquiring the read lock.
146     * @param errMsg Error msg to log in case of error.
147     * @param secondOP Set to NO_MORE_OP if a 2nd lock request is not required.
148     * Set to INVOKE_READ, INVOKE_READ or INVOKE_UPGRADE
149     * respectively if the 2nd lock is a read, write or
150     * upgrade request respectively.
151     */

152   
153    protected Thread JavaDoc readThread(final String JavaDoc caseNum, final String JavaDoc name,
154                                final long msecs, final long sleepSecs,
155                                final String JavaDoc errMsg, final int secondOP)
156    {
157       return new Thread JavaDoc(name)
158       {
159          public void run()
160          {
161                Sync rlock = lock_.readLock();
162             try {
163                if (! rlock.attempt(msecs)) {
164                   logX(caseNum+"-"+name+" requesting read lock failed!\n");
165                   String JavaDoc str = caseNum + "-" + name + "-RL-0";
166                   postLockingResult(str);
167                   return;
168                }
169                // OK, read lock obtained, sleep and release it.
170
logX(caseNum+"-"+name+" requesting read lock succeeded!\n");
171                String JavaDoc str = caseNum + "-" + name + "-RL-1";
172                postLockingResult(str);
173                _sleep(sleepSecs);
174
175            if (secondOP == INVOKE_READ)
176                    acquireReadLock(caseNum, name, msecs, errMsg);
177                else if (secondOP == INVOKE_WRITE)
178                    acquireWriteLock(caseNum, name, msecs, errMsg);
179                else if (secondOP == INVOKE_UPGRADE)
180                    acquireUpgradeLock(caseNum, name, msecs, errMsg);
181                  
182                rlock.release();
183                logX(caseNum+"-"+name+" releasing read lock.\n");
184             } catch (Exception JavaDoc ex) {
185             }
186          }
187       };
188    }
189
190    /**
191     * Creates a new thread and acquires a write lock with a timeout
192     * value specified by the caller. Similar to {@link #readThread readThread()}
193     * except it's used for write locks.
194     * @see #readThread readThread()
195     */

196    protected Thread JavaDoc writeThread(final String JavaDoc caseNum, final String JavaDoc name,
197                                 final long msecs, final long sleepSecs,
198                                 final String JavaDoc errMsg, final int secondOP)
199    {
200       return new Thread JavaDoc(name)
201       {
202          public void run()
203          {
204             try {
205                Sync wlock = lock_.writeLock();
206                if (! wlock.attempt(msecs)) {
207                   logX(caseNum+"-"+name+" requesting write lock failed!\n");
208                   String JavaDoc str = caseNum + "-" + name + "-WL-0";
209                   postLockingResult(str);
210                   return;
211                }
212                // OK, write lock obtained, sleep and release it.
213
logX(caseNum+"-"+name+" requesting write lock succeeded!\n");
214                String JavaDoc str = caseNum + "-" + name + "-WL-1";
215                postLockingResult(str);
216                _sleep(sleepSecs);
217
218            if (secondOP == INVOKE_READ)
219                    acquireReadLock(caseNum, name, msecs, errMsg);
220                else if (secondOP == INVOKE_WRITE)
221                    acquireWriteLock(caseNum, name, msecs, errMsg);
222                else if (secondOP == INVOKE_UPGRADE)
223                    acquireUpgradeLock(caseNum, name, msecs, errMsg);
224
225                wlock.release();
226                logX(caseNum+"-"+name+" releasing write lock.\n");
227             } catch (Exception JavaDoc ex) {
228             }
229          }
230       };
231    }
232
233    /**
234     * Creates a new thread, acquires a read lock, sleeps for a while
235     * and then tries to upgrade the read lock to a write one. Similar
236     * to {@link #readThread readThread()} except it's used for upgrading
237     * locks.
238     * @see #readThread readThread()
239     */

240    protected Thread JavaDoc upgradeThread(final String JavaDoc caseNum, final String JavaDoc name,
241                                   final long msecs, final String JavaDoc errMsg)
242    {
243       return new Thread JavaDoc(name)
244       {
245          public void run()
246          {
247             try {
248                Sync rlock = lock_.readLock();
249                Sync wlock = null;
250                if (! rlock.attempt(msecs)) {
251                   logX(caseNum+"-"+name+" requesting read lock failed!\n");
252                   String JavaDoc str = caseNum + "-" + name + "-RL-0";
253                   postLockingResult(str);
254                   return;
255                }
256                // OK, read lock obtained, sleep and upgrade it later.
257
logX(caseNum+"-"+name+" requesting read lock succeeded (upgrade later)!\n");
258                _sleep(SLEEP_MSECS/2);
259                String JavaDoc str = caseNum + "-" + name + "-UL-";
260                if ((wlock = lock_.upgradeLockAttempt(msecs)) == null)
261                {
262                  logX(caseNum+"-"+name+" requesting upgrade lock failed!\n");
263                  str += "0";
264                }
265                else
266                {
267                  logX(caseNum+"-"+name+" requesting upgrade lock succeeded!\n");
268                  str += "1";
269                }
270                postLockingResult(str);
271                // Sleep again and then release the lock.
272
_sleep(SLEEP_MSECS);
273                if (wlock != null)
274                {
275                  wlock.release();
276                  logX(caseNum+"-"+name+" releasing upgrade lock.\n");
277                }
278                rlock.release();
279             } catch (Exception JavaDoc ex) {
280             }
281          }
282       };
283    }
284
285    /***************************************************************/
286    /* Utility functions to acquire RL and WL (no thread) */
287    /***************************************************************/
288    /**
289     * This routine tries to acquire a read lock with a timeout value
290     * passed in by the caller. Like {@link #readThread readThread()}
291     * it then stores the locking result in the result vector depending
292     * on the outcome of the request.
293     */

294   
295    protected void acquireReadLock(final String JavaDoc caseNum, final String JavaDoc name,
296                                   final long msecs, final String JavaDoc errMsg)
297    {
298             try {
299                Sync rlock = lock_.readLock();
300                if (! rlock.attempt(msecs)) {
301                   logX(caseNum+"-"+name+" requesting read lock failed!\n");
302                   String JavaDoc str = caseNum + "-" + name + "-RL-0";
303                   postLockingResult(str);
304                   return;
305                }
306                // OK, read lock obtained, sleep and release it.
307
logX(caseNum+"-"+name+" requesting read lock succeeded!\n");
308                String JavaDoc str = caseNum + "-" + name + "-RL-1";
309                postLockingResult(str);
310                _sleep(SLEEP_MSECS);
311                rlock.release();
312                logX(caseNum+"-"+name+" releasing read lock.\n");
313             } catch (Exception JavaDoc ex) {
314             }
315    }
316
317    /**
318     * Same as {@link #acquireReadLock acquireReadLock()} except
319     * it's for write lock request.
320     */

321    protected void acquireWriteLock(final String JavaDoc caseNum, final String JavaDoc name,
322                                    final long msecs, final String JavaDoc errMsg)
323    {
324             try {
325                Sync wlock = lock_.writeLock();
326                if (! wlock.attempt(msecs)) {
327                   logX(caseNum+"-"+name+" requesting write lock failed!\n");
328                   String JavaDoc str = caseNum + "-" + name + "-WL-0";
329                   postLockingResult(str);
330                   return;
331                }
332                // OK, write lock obtained, sleep and release it.
333
logX(caseNum+"-"+name+" requesting write lock succeeded!\n");
334                String JavaDoc str = caseNum + "-" + name + "-WL-1";
335                postLockingResult(str);
336                _sleep(SLEEP_MSECS);
337                wlock.release();
338                logX(caseNum+"-"+name+" releasing write lock.\n");
339             } catch (Exception JavaDoc ex) {
340             }
341    }
342
343    /**
344     * Same as {@link #acquireReadLock acquireReadLock()} except
345     * it's for upgrade lock request.
346     */

347    protected void acquireUpgradeLock(final String JavaDoc caseNum, final String JavaDoc name,
348                                      final long msecs, final String JavaDoc errMsg)
349    {
350             try {
351                Sync ulock = null;
352                if ((ulock = lock_.upgradeLockAttempt(msecs)) == null) {
353                   logX(caseNum+"-"+name+" requesting upgrade lock failed!\n");
354                   String JavaDoc str = caseNum + "-" + name + "-UL-0";
355                   postLockingResult(str);
356                   return;
357                }
358                // OK, write lock obtained, sleep and release it.
359
logX(caseNum+"-"+name+" requesting upgrade lock succeeded!\n");
360                String JavaDoc str = caseNum + "-" + name + "-UL-1";
361                postLockingResult(str);
362                _sleep(SLEEP_MSECS);
363                ulock.release();
364                logX(caseNum+"-"+name+" releasing upgrade lock.\n");
365             } catch (Exception JavaDoc ex) {
366             }
367    }
368
369    /***************************************************************/
370    /* Synchronized methods handling locking result vector */
371    /***************************************************************/
372    /**
373     * Clean/remove all locking results in the vector.
374     */

375    protected synchronized void cleanLockingResult()
376    {
377        lockResult.removeAllElements();
378    }
379
380    /**
381     * Post a locking result to the vector for later verification.
382     */

383    protected synchronized void postLockingResult(Object JavaDoc obj)
384    {
385        logX(" Added *" + (String JavaDoc)obj + "* to the result vector\n");
386        // Make sure we only have one in the vector
387
//if (!checkLockingResult((String)obj))
388
lockResult.addElement(obj);
389    }
390    
391    /**
392     * Check if a given expected locking result is in the vector.
393     */

394    protected synchronized boolean checkLockingResult(String JavaDoc expected)
395    {
396        boolean rc = false;
397        for (int i=0; i<lockResult.size(); i++)
398        {
399          Object JavaDoc ele = lockResult.elementAt(i);
400          String JavaDoc str = (String JavaDoc)ele;
401          if (expected.equals(str))
402          {
403             rc = true;
404             break;
405          }
406        }
407        if (rc)
408          logX(" Searching for *" + expected + "* SUCCEEDED.\n");
409        else
410          logX(" Searching for *" + expected + "* FAILED.\n");
411        return rc;
412    }
413
414    /***************************************************************/
415    /* T e s t C a s e s */
416    /***************************************************************/
417    /** Case #10 - T1 acquires RL, T2 acquires RL followed by WL. */
418    public void testWriteWithMultipleReaders() throws Exception JavaDoc
419    {
420       String JavaDoc caseNum = "10";
421       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS*2,
422                            "1st read lock attempt failed", NO_MORE_OP);
423       Thread JavaDoc t2=readThread(caseNum, "t2", 0, SLEEP_MSECS,
424                            "2nd read lock attempt failed", INVOKE_WRITE);
425
426       t1.start();
427       t2.start();
428       t1.join(3000);
429       t2.join(3000);
430       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
431                  checkLockingResult(caseNum+"-t2-RL-1") &&
432                  checkLockingResult(caseNum+"-t2-WL-0"));
433       cleanLockingResult();
434       // possilbe deadlock check
435
if (t1.isAlive() || t2.isAlive())
436          fail("Possible deadlock resulted in testRead.");
437    }
438
439    /** Case #11 - T1 acquires RL followed by WL, T2 acquires RL. */
440    public void testUpgradeWithMultipleReadersOn1() throws Exception JavaDoc
441    {
442       String JavaDoc caseNum = "11";
443       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS,
444                            "1st read lock attempt failed", INVOKE_WRITE);
445       Thread JavaDoc t2=readThread(caseNum, "t2", 0, SLEEP_MSECS*2,
446                            "2nd read lock attempt failed", NO_MORE_OP);
447
448       t1.start();
449       t2.start();
450       t1.join(3000);
451       t2.join(3000);
452       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
453                  checkLockingResult(caseNum+"-t2-RL-1") &&
454                  checkLockingResult(caseNum+"-t1-WL-0"));
455       cleanLockingResult();
456       // possilbe deadlock check
457
if (t1.isAlive() || t2.isAlive())
458          fail("Possible deadlock resulted in testRead.");
459    }
460
461    /** Case #2 - T1 acquires RL followed by UL. */
462    public void testUpgradeReadLock() throws Exception JavaDoc
463    {
464       String JavaDoc caseNum = "2";
465       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS,
466                            "1st read lock attempt failed", INVOKE_UPGRADE);
467
468       t1.start();
469       t1.join(3000);
470       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
471                  checkLockingResult(caseNum+"-t1-UL-1"));
472       cleanLockingResult();
473    }
474
475    /** Case #3 - T1 acquires RL followed by WL. */
476
477    public void testReadThenWrite() throws Exception JavaDoc
478    {
479       String JavaDoc caseNum = "3";
480       acquireReadLock(caseNum, "t1", 0, "1st read lock attempt failed");
481       acquireWriteLock(caseNum, "t1.1", 0, "2nd write lock attempt failed");
482       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
483                  checkLockingResult(caseNum+"-t1.1-WL-1"));
484       cleanLockingResult();
485    }
486
487
488    /** Case #5 - T1 acquires WL followed by RL.*/
489
490    public void testWriteThenRead() throws Exception JavaDoc
491    {
492       String JavaDoc caseNum = "5";
493       acquireWriteLock(caseNum, "t1", 0, "1st write lock attempt failed");
494       acquireReadLock(caseNum, "t1.1", 0, "2nd read lock attempt failed");
495       assertTrue(checkLockingResult(caseNum+"-t1-WL-1") &&
496                  checkLockingResult(caseNum+"-t1.1-RL-1"));
497       cleanLockingResult();
498    }
499
500    /** Case #6 - T1 acquires RL, T2 acquires RL.*/
501    public void testMultipleReadlock() throws Exception JavaDoc
502    {
503       String JavaDoc caseNum = "6";
504       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS,
505                            "1st read lock attempt failed", NO_MORE_OP);
506       Thread JavaDoc t2=readThread(caseNum, "t2", 0, SLEEP_MSECS,
507                            "2nd read lock attempt failed", NO_MORE_OP);
508
509       t1.start();
510       t2.start();
511       t1.join(3000);
512       t2.join(3000);
513       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
514                  checkLockingResult(caseNum+"-t2-RL-1"));
515       cleanLockingResult();
516       // possilbe deadlock check
517
if (t1.isAlive() || t2.isAlive())
518          fail("Possible deadlock resulted in testRead.");
519    }
520
521    /** Case #8 - T1 acquires WL, T2 acquires RL.*/
522    public void testWriteWithExistingReader() throws Exception JavaDoc
523    {
524       String JavaDoc caseNum = "8";
525       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS,
526                            "1st write lock attempt failed", NO_MORE_OP);
527       Thread JavaDoc t2=writeThread(caseNum, "t2", 0, SLEEP_MSECS,
528                            "2nd read lock attempt failed", NO_MORE_OP);
529
530       t1.start();
531       t2.start();
532       t1.join(3000);
533       t2.join(3000);
534       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
535                  checkLockingResult(caseNum+"-t2-WL-0"));
536       cleanLockingResult();
537       // possilbe deadlock check
538
if (t1.isAlive() || t2.isAlive())
539          fail("Possible deadlock resulted in testRead.");
540    }
541
542    /** Case #13 - T1 acquires RL, T2 acquires WL.*/
543    public void testReadWithExistingWriter() throws Exception JavaDoc
544    {
545       String JavaDoc caseNum = "13";
546       Thread JavaDoc t1=writeThread(caseNum, "t1", 0, SLEEP_MSECS,
547                            "1st write lock attempt failed", NO_MORE_OP);
548       Thread JavaDoc t2=readThread(caseNum, "t2", 0, SLEEP_MSECS,
549                            "2nd read lock attempt failed", NO_MORE_OP);
550
551       t1.start();
552       t2.start();
553       t1.join(3000);
554       t2.join(3000);
555       assertTrue(checkLockingResult(caseNum+"-t1-WL-1") &&
556                  checkLockingResult(caseNum+"-t2-RL-0"));
557       cleanLockingResult();
558       // possilbe deadlock check
559
if (t1.isAlive() || t2.isAlive())
560          fail("Possible deadlock resulted in testRead.");
561    }
562
563    /** Case #14 - T1 acquires WL, T2 acquires WL.*/
564    public void testMultipleWritelocks() throws Exception JavaDoc
565    {
566       String JavaDoc caseNum = "14";
567       Thread JavaDoc t1=writeThread(caseNum, "t1", 0, SLEEP_MSECS,
568                            "1st write lock attempt failed", NO_MORE_OP);
569       Thread JavaDoc t2=writeThread(caseNum, "t2", 0, SLEEP_MSECS,
570                            "2nd write lock attempt failed", NO_MORE_OP);
571
572       t1.start();
573       t2.start();
574       t1.join(3000);
575       t2.join(3000);
576       assertTrue(checkLockingResult(caseNum+"-t1-WL-1") &&
577                  checkLockingResult(caseNum+"-t2-WL-0"));
578       cleanLockingResult();
579       // possilbe deadlock check
580
if (t1.isAlive() || t2.isAlive())
581          fail("Possible deadlock resulted in testRead.");
582    }
583    /** Case #7 - T1 acquires RL, T2 acquires UL.*/
584
585    public void testUpgradeWithExistingReader() throws Exception JavaDoc
586    {
587       String JavaDoc caseNum = "7";
588       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS,
589                            "1st read lock attempt failed", NO_MORE_OP);
590       Thread JavaDoc t2=upgradeThread(caseNum, "t2", 0,
591                            "2nd upgrade lock attempt failed");
592
593       t1.start();
594       t2.start();
595       t1.join(3000);
596       t2.join(3000);
597       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
598                  checkLockingResult(caseNum+"-t2-UL-0"));
599       cleanLockingResult();
600       // possilbe deadlock check
601
if (t1.isAlive() || t2.isAlive())
602          fail("Possible deadlock resulted in testRead.");
603    }
604
605    /** Case #9 - T1 acquires RL, T2 acquires RL followed by UL.*/
606    public void testUpgradeWithMultipleReaders() throws Exception JavaDoc
607    {
608       String JavaDoc caseNum = "9";
609       Thread JavaDoc t1=readThread(caseNum, "t1", 0, SLEEP_MSECS*2,
610                            "1st read lock attempt failed", NO_MORE_OP);
611       Thread JavaDoc t2=readThread(caseNum, "t2", 0, SLEEP_MSECS,
612                            "2nd read lock attempt failed", INVOKE_UPGRADE);
613
614       t1.start();
615       t2.start();
616       t1.join(3000);
617       t2.join(3000);
618       assertTrue(checkLockingResult(caseNum+"-t1-RL-1") &&
619                  checkLockingResult(caseNum+"-t2-RL-1") &&
620                  checkLockingResult(caseNum+"-t2-UL-0"));
621       cleanLockingResult();
622       // possilbe deadlock check
623
if (t1.isAlive() || t2.isAlive())
624          fail("Possible deadlock resulted in testRead.");
625    }
626 }
627
628
Popular Tags