32 import java.util.concurrent.CyclicBarrier;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Executors;
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
37 import java.util.concurrent.locks.Condition;
38 import java.util.concurrent.locks.Lock;
39
40 /**
41 * This uses a variant of the standard Mutex demo, except with a
42 * tryAcquire method that randomly throws various Throwable
43 * subclasses.
44 */
45 @SuppressWarnings("serial")
46 public class FlakyMutex implements Lock {
47 static class MyError extends Error {}
48 static class MyException extends Exception {}
49 static class MyRuntimeException extends RuntimeException {}
50
51 static void checkThrowable(Throwable t) {
52 check((t instanceof MyError) ||
53 (t instanceof MyException) ||
54 (t instanceof MyRuntimeException));
55 }
56
57 static void realMain(String[] args) throws Throwable {
58 final int nThreads = 3;
59 final int iterations = 10_000;
60 final CyclicBarrier startingGate = new CyclicBarrier(nThreads);
61 final FlakyMutex mutex = new FlakyMutex();
62 final ExecutorService es = Executors.newFixedThreadPool(nThreads);
63 final Runnable task = () -> {
64 try {
65 startingGate.await();
66 for (int i = 0; i < iterations; i++) {
67 for (;;) {
68 try { mutex.lock(); break; }
69 catch (Throwable t) { checkThrowable(t); }
70 }
71
72 try { check(! mutex.tryLock()); }
73 catch (Throwable t) { checkThrowable(t); }
74
75 try { check(! mutex.tryLock(1, TimeUnit.MICROSECONDS)); }
76 catch (Throwable t) { checkThrowable(t); }
77
78 mutex.unlock();
79 }
80 } catch (Throwable t) { unexpected(t); }
81 };
82
83 for (int i = 0; i < nThreads; i++)
84 es.submit(task);
85 es.shutdown();
86 // Let test harness handle timeout
87 check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS));
88 }
89
90 private static class FlakySync extends AbstractQueuedLongSynchronizer {
91 private static final long serialVersionUID = -1L;
92
93 public boolean isHeldExclusively() { return getState() == 1; }
94
95 public boolean tryAcquire(long acquires) {
96 // Sneak in some tests for queue state
129 }
130 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
131 return sync.tryAcquireNanos(1, unit.toNanos(timeout));
132 }
133 public void unlock() { sync.release(1); }
134 public Condition newCondition() { return sync.newCondition(); }
135 public boolean isLocked() { return sync.isHeldExclusively(); }
136 public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
137
138 //--------------------- Infrastructure ---------------------------
139 static volatile int passed = 0, failed = 0;
140 static void pass() {passed++;}
141 static void fail() {failed++; Thread.dumpStack();}
142 static void fail(String msg) {System.out.println(msg); fail();}
143 static void unexpected(Throwable t) {failed++; t.printStackTrace();}
144 static void check(boolean cond) {if (cond) pass(); else fail();}
145 static void equal(Object x, Object y) {
146 if (x == null ? y == null : x.equals(y)) pass();
147 else fail(x + " not equal to " + y);}
148 public static void main(String[] args) throws Throwable {
149 try {realMain(args);} catch (Throwable t) {unexpected(t);}
150 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
151 if (failed > 0) throw new AssertionError("Some tests failed");}
152 @SuppressWarnings("unchecked")
153 static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
154 throw (T)t; // rely on vacuous cast
155 }
156 }
|
32 import java.util.concurrent.CyclicBarrier;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Executors;
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
37 import java.util.concurrent.locks.Condition;
38 import java.util.concurrent.locks.Lock;
39
40 /**
41 * This uses a variant of the standard Mutex demo, except with a
42 * tryAcquire method that randomly throws various Throwable
43 * subclasses.
44 */
45 @SuppressWarnings("serial")
46 public class FlakyMutex implements Lock {
47 static class MyError extends Error {}
48 static class MyException extends Exception {}
49 static class MyRuntimeException extends RuntimeException {}
50
51 static void checkThrowable(Throwable t) {
52 if (!((t instanceof MyError) ||
53 (t instanceof MyException) ||
54 (t instanceof MyRuntimeException)))
55 unexpected(t);
56 }
57
58 static void realMain(String[] args) throws Throwable {
59 final ThreadLocalRandom rndMain = ThreadLocalRandom.current();
60 final int nCpus = Runtime.getRuntime().availableProcessors();
61 final int maxThreads = Math.min(4, nCpus);
62 final int nThreads = rndMain.nextInt(1, maxThreads + 1);
63 final int iterations = 10_000;
64 final CyclicBarrier startingGate = new CyclicBarrier(nThreads);
65 final ExecutorService es = Executors.newFixedThreadPool(nThreads);
66 final FlakyMutex mutex = new FlakyMutex();
67 final Runnable task = () -> {
68 try {
69 ThreadLocalRandom rnd = ThreadLocalRandom.current();
70 startingGate.await();
71 for (int i = 0; i < iterations; i++) {
72 for (;;) {
73 try {
74 if (rnd.nextBoolean())
75 mutex.lock();
76 else
77 mutex.lockInterruptibly();
78 break;
79 } catch (Throwable t) { checkThrowable(t); }
80 }
81
82 if (rnd.nextBoolean()) {
83 try {
84 check(! mutex.tryLock());
85 } catch (Throwable t) { checkThrowable(t); }
86 }
87
88 if (rnd.nextInt(10) == 0) {
89 try {
90 check(! mutex.tryLock(1, TimeUnit.MICROSECONDS));
91 } catch (Throwable t) { checkThrowable(t); }
92 }
93
94 if (rnd.nextBoolean()) {
95 check(mutex.isLocked());
96 }
97
98 mutex.unlock();
99 }
100 } catch (Throwable t) { unexpected(t); }
101 };
102
103 for (int i = 0; i < nThreads; i++)
104 es.submit(task);
105 es.shutdown();
106 // Let test harness handle timeout
107 check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS));
108 }
109
110 private static class FlakySync extends AbstractQueuedLongSynchronizer {
111 private static final long serialVersionUID = -1L;
112
113 public boolean isHeldExclusively() { return getState() == 1; }
114
115 public boolean tryAcquire(long acquires) {
116 // Sneak in some tests for queue state
149 }
150 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
151 return sync.tryAcquireNanos(1, unit.toNanos(timeout));
152 }
153 public void unlock() { sync.release(1); }
154 public Condition newCondition() { return sync.newCondition(); }
155 public boolean isLocked() { return sync.isHeldExclusively(); }
156 public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
157
158 //--------------------- Infrastructure ---------------------------
159 static volatile int passed = 0, failed = 0;
160 static void pass() {passed++;}
161 static void fail() {failed++; Thread.dumpStack();}
162 static void fail(String msg) {System.out.println(msg); fail();}
163 static void unexpected(Throwable t) {failed++; t.printStackTrace();}
164 static void check(boolean cond) {if (cond) pass(); else fail();}
165 static void equal(Object x, Object y) {
166 if (x == null ? y == null : x.equals(y)) pass();
167 else fail(x + " not equal to " + y);}
168 public static void main(String[] args) throws Throwable {
169 int runsPerTest = Integer.getInteger("jsr166.runsPerTest", 1);
170 try {
171 for (int i = runsPerTest; i--> 0; )
172 realMain(args);
173 } catch (Throwable t) { unexpected(t); }
174 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
175 if (failed > 0) throw new AssertionError("Some tests failed");}
176 @SuppressWarnings("unchecked")
177 static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
178 throw (T)t; // rely on vacuous cast
179 }
180 }
|