1 10 11 package com.triactive.jdo.util.test; 12 13 import com.triactive.jdo.util.ReadWriteLock; 14 import java.util.Random ; 15 import junit.framework.TestCase; 16 17 18 24 25 public class ReadWriteLockTest extends TestCase 26 { 27 private static final int MAX_TEST_TIME = 30; 28 private static final int NUM_TEST_THREADS = 10; 29 private static final int NUM_OUTER_ITERATIONS = 500; 30 private static final int NUM_INNER_ITERATIONS = 2500; 31 private static final int YIELD_FREQUENCY = 250; 32 33 private Throwable threadFailure; 34 35 36 42 43 public ReadWriteLockTest(String name) 44 { 45 super(name); 46 } 47 48 49 public void testBasicFunction() throws Throwable 50 { 51 ThreadGroup group = new ThreadGroup ("ReadWriteLockTest"); 52 Thread [] threads = new Thread [NUM_TEST_THREADS]; 53 ReadWriteLock rwl = new ReadWriteLock(); 54 Object [] objs = new Object [1]; 55 56 59 for (int i = 0; i < NUM_TEST_THREADS; ++i) 60 threads[i] = new Thread (group, new TestThread(new Random (i), rwl, objs), "Test thread #" + i); 61 62 threadFailure = null; 63 64 for (int i = 0; i < NUM_TEST_THREADS; ++i) 65 threads[i].start(); 66 67 71 long startTime = System.currentTimeMillis(); 72 int runningThreads; 73 74 do 75 { 76 runningThreads = group.enumerate(threads); 77 78 for (int i = 0; i < runningThreads; ++i) 79 { 80 threads[i].join(250); 81 82 if (System.currentTimeMillis() - startTime > MAX_TEST_TIME * 1000) 83 { 84 for (int j = 0; j < runningThreads; ++j) 85 threads[j].interrupt(); 86 87 fail("Test has taken more than " + MAX_TEST_TIME + " seconds; it is assumed to be deadlocked"); 88 } 89 } 90 } while (runningThreads > 0); 91 92 96 if (threadFailure != null) 97 throw threadFailure; 98 } 99 100 101 private class TestThread implements Runnable 102 { 103 private final Random rnd; 104 private final ReadWriteLock rwl; 105 private final Object [] objs; 106 107 public TestThread(Random rnd, ReadWriteLock rwl, Object [] objs) 108 { 109 this.rnd = rnd; 110 this.rwl = rwl; 111 this.objs = objs; 112 } 113 114 115 public void run() 116 { 117 try 118 { 119 123 final String [] lockPatterns = 124 { 125 126 "R", "W", 127 "RR", "WR", "WW", 128 "RRR", "WRR", "WWR", "WWW", 129 130 131 "RW", "RRW", "RRRW", "RRRRW" 132 }; 133 134 for (int i = 0; i < NUM_OUTER_ITERATIONS && threadFailure == null; ++i) 135 { 136 String pattern = lockPatterns[rnd.nextInt(lockPatterns.length)]; 137 boolean isLegalPattern = pattern.indexOf("RW") == -1; 138 139 try 140 { 141 tryPattern(pattern); 142 143 if (!isLegalPattern) 144 fail("Illegal nested lock sequence " + pattern + " should have thrown an IllegalStateException"); 145 } 146 catch (IllegalStateException e) 147 { 148 if (isLegalPattern) 149 throw e; 150 } 151 } 152 } 153 catch (Throwable t) 154 { 155 threadFailure = t; 156 } 157 } 158 159 160 private void tryPattern(String lockPattern) throws InterruptedException 161 { 162 boolean isWriteLock = lockPattern.charAt(0) == 'W'; 163 164 if (isWriteLock) 165 rwl.writeLock(); 166 else 167 rwl.readLock(); 168 169 try 170 { 171 Object obj; 172 173 177 if (isWriteLock) 178 { 179 obj = this; 180 objs[0] = obj; 181 } 182 else 183 obj = objs[0]; 184 185 189 for (int i = 0; i < NUM_INNER_ITERATIONS; ++i) 190 { 191 ReadWriteLockTest.this.assertSame(obj, objs[0]); 192 193 if (i % YIELD_FREQUENCY == 0) 194 Thread.yield(); 195 } 196 197 200 if (lockPattern.length() > 1) 201 tryPattern(lockPattern.substring(1)); 202 } 203 finally 204 { 205 rwl.unlock(); 206 } 207 } 208 } 209 } 210 | Popular Tags |