ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/LockSupportTest.java
Revision: 1.27
Committed: Fri May 12 18:12:52 2017 UTC (7 years ago) by jsr166
Branch: MAIN
Changes since 1.26: +2 -1 lines
Log Message:
introduce MAX_SPURIOUS_WAKEUPS

File Contents

# Content
1 /*
2 * Written by Doug Lea and Martin Buchholz with assistance from
3 * members of JCP JSR-166 Expert Group and released to the public
4 * domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 * Other contributors include Andrew Wright, Jeffrey Hayes,
7 * Pat Fisher, Mike Judd.
8 */
9
10 import static java.util.concurrent.TimeUnit.MILLISECONDS;
11
12 import java.util.concurrent.CountDownLatch;
13 import java.util.concurrent.atomic.AtomicBoolean;
14 import java.util.concurrent.locks.LockSupport;
15
16 import junit.framework.Test;
17 import junit.framework.TestSuite;
18
19 public class LockSupportTest extends JSR166TestCase {
20 public static void main(String[] args) {
21 main(suite(), args);
22 }
23
24 public static Test suite() {
25 return new TestSuite(LockSupportTest.class);
26 }
27
28 static {
29 // Reduce the risk of rare disastrous classloading in first call to
30 // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
31 Class<?> ensureLoaded = LockSupport.class;
32 }
33
34 /**
35 * Returns the blocker object used by tests in this file.
36 * Any old object will do; we'll return a convenient one.
37 */
38 static Object theBlocker() {
39 return LockSupportTest.class;
40 }
41
42 enum ParkMethod {
43 park() {
44 void park() {
45 LockSupport.park();
46 }
47 void park(long millis) {
48 throw new UnsupportedOperationException();
49 }
50 },
51 parkUntil() {
52 void park(long millis) {
53 LockSupport.parkUntil(deadline(millis));
54 }
55 },
56 parkNanos() {
57 void park(long millis) {
58 LockSupport.parkNanos(MILLISECONDS.toNanos(millis));
59 }
60 },
61 parkBlocker() {
62 void park() {
63 LockSupport.park(theBlocker());
64 }
65 void park(long millis) {
66 throw new UnsupportedOperationException();
67 }
68 },
69 parkUntilBlocker() {
70 void park(long millis) {
71 LockSupport.parkUntil(theBlocker(), deadline(millis));
72 }
73 },
74 parkNanosBlocker() {
75 void park(long millis) {
76 LockSupport.parkNanos(theBlocker(),
77 MILLISECONDS.toNanos(millis));
78 }
79 };
80
81 void park() { park(2 * LONG_DELAY_MS); }
82 abstract void park(long millis);
83
84 /** Returns a deadline to use with parkUntil. */
85 long deadline(long millis) {
86 // beware of rounding
87 return System.currentTimeMillis() + millis + 1;
88 }
89 }
90
91 /**
92 * park is released by subsequent unpark
93 */
94 public void testParkBeforeUnpark_park() {
95 testParkBeforeUnpark(ParkMethod.park);
96 }
97 public void testParkBeforeUnpark_parkNanos() {
98 testParkBeforeUnpark(ParkMethod.parkNanos);
99 }
100 public void testParkBeforeUnpark_parkUntil() {
101 testParkBeforeUnpark(ParkMethod.parkUntil);
102 }
103 public void testParkBeforeUnpark_parkBlocker() {
104 testParkBeforeUnpark(ParkMethod.parkBlocker);
105 }
106 public void testParkBeforeUnpark_parkNanosBlocker() {
107 testParkBeforeUnpark(ParkMethod.parkNanosBlocker);
108 }
109 public void testParkBeforeUnpark_parkUntilBlocker() {
110 testParkBeforeUnpark(ParkMethod.parkUntilBlocker);
111 }
112 public void testParkBeforeUnpark(final ParkMethod parkMethod) {
113 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
114 Thread t = newStartedThread(new CheckedRunnable() {
115 public void realRun() {
116 pleaseUnpark.countDown();
117 parkMethod.park();
118 }});
119
120 await(pleaseUnpark);
121 LockSupport.unpark(t);
122 awaitTermination(t);
123 }
124
125 /**
126 * park is released by preceding unpark
127 */
128 public void testParkAfterUnpark_park() {
129 testParkAfterUnpark(ParkMethod.park);
130 }
131 public void testParkAfterUnpark_parkNanos() {
132 testParkAfterUnpark(ParkMethod.parkNanos);
133 }
134 public void testParkAfterUnpark_parkUntil() {
135 testParkAfterUnpark(ParkMethod.parkUntil);
136 }
137 public void testParkAfterUnpark_parkBlocker() {
138 testParkAfterUnpark(ParkMethod.parkBlocker);
139 }
140 public void testParkAfterUnpark_parkNanosBlocker() {
141 testParkAfterUnpark(ParkMethod.parkNanosBlocker);
142 }
143 public void testParkAfterUnpark_parkUntilBlocker() {
144 testParkAfterUnpark(ParkMethod.parkUntilBlocker);
145 }
146 public void testParkAfterUnpark(final ParkMethod parkMethod) {
147 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
148 final AtomicBoolean pleasePark = new AtomicBoolean(false);
149 Thread t = newStartedThread(new CheckedRunnable() {
150 public void realRun() {
151 pleaseUnpark.countDown();
152 while (!pleasePark.get())
153 Thread.yield();
154 parkMethod.park();
155 }});
156
157 await(pleaseUnpark);
158 LockSupport.unpark(t);
159 pleasePark.set(true);
160 awaitTermination(t);
161 }
162
163 /**
164 * park is released by subsequent interrupt
165 */
166 public void testParkBeforeInterrupt_park() {
167 testParkBeforeInterrupt(ParkMethod.park);
168 }
169 public void testParkBeforeInterrupt_parkNanos() {
170 testParkBeforeInterrupt(ParkMethod.parkNanos);
171 }
172 public void testParkBeforeInterrupt_parkUntil() {
173 testParkBeforeInterrupt(ParkMethod.parkUntil);
174 }
175 public void testParkBeforeInterrupt_parkBlocker() {
176 testParkBeforeInterrupt(ParkMethod.parkBlocker);
177 }
178 public void testParkBeforeInterrupt_parkNanosBlocker() {
179 testParkBeforeInterrupt(ParkMethod.parkNanosBlocker);
180 }
181 public void testParkBeforeInterrupt_parkUntilBlocker() {
182 testParkBeforeInterrupt(ParkMethod.parkUntilBlocker);
183 }
184 public void testParkBeforeInterrupt(final ParkMethod parkMethod) {
185 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
186 Thread t = newStartedThread(new CheckedRunnable() {
187 public void realRun() {
188 pleaseInterrupt.countDown();
189 do {
190 parkMethod.park();
191 // park may return spuriously
192 } while (! Thread.currentThread().isInterrupted());
193 }});
194
195 await(pleaseInterrupt);
196 assertThreadStaysAlive(t);
197 t.interrupt();
198 awaitTermination(t);
199 }
200
201 /**
202 * park is released by preceding interrupt
203 */
204 public void testParkAfterInterrupt_park() {
205 testParkAfterInterrupt(ParkMethod.park);
206 }
207 public void testParkAfterInterrupt_parkNanos() {
208 testParkAfterInterrupt(ParkMethod.parkNanos);
209 }
210 public void testParkAfterInterrupt_parkUntil() {
211 testParkAfterInterrupt(ParkMethod.parkUntil);
212 }
213 public void testParkAfterInterrupt_parkBlocker() {
214 testParkAfterInterrupt(ParkMethod.parkBlocker);
215 }
216 public void testParkAfterInterrupt_parkNanosBlocker() {
217 testParkAfterInterrupt(ParkMethod.parkNanosBlocker);
218 }
219 public void testParkAfterInterrupt_parkUntilBlocker() {
220 testParkAfterInterrupt(ParkMethod.parkUntilBlocker);
221 }
222 public void testParkAfterInterrupt(final ParkMethod parkMethod) {
223 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
224 final AtomicBoolean pleasePark = new AtomicBoolean(false);
225 Thread t = newStartedThread(new CheckedRunnable() {
226 public void realRun() throws Exception {
227 pleaseInterrupt.countDown();
228 while (!pleasePark.get())
229 Thread.yield();
230 assertTrue(Thread.currentThread().isInterrupted());
231 parkMethod.park();
232 assertTrue(Thread.currentThread().isInterrupted());
233 }});
234
235 await(pleaseInterrupt);
236 t.interrupt();
237 pleasePark.set(true);
238 awaitTermination(t);
239 }
240
241 /**
242 * timed park times out if not unparked
243 */
244 public void testParkTimesOut_parkNanos() {
245 testParkTimesOut(ParkMethod.parkNanos);
246 }
247 public void testParkTimesOut_parkUntil() {
248 testParkTimesOut(ParkMethod.parkUntil);
249 }
250 public void testParkTimesOut_parkNanosBlocker() {
251 testParkTimesOut(ParkMethod.parkNanosBlocker);
252 }
253 public void testParkTimesOut_parkUntilBlocker() {
254 testParkTimesOut(ParkMethod.parkUntilBlocker);
255 }
256 public void testParkTimesOut(final ParkMethod parkMethod) {
257 Thread t = newStartedThread(new CheckedRunnable() {
258 public void realRun() {
259 for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
260 long startTime = System.nanoTime();
261 parkMethod.park(timeoutMillis());
262 // park may return spuriously
263 if (millisElapsedSince(startTime) >= timeoutMillis())
264 return;
265 }
266 fail("too many consecutive spurious wakeups?");
267 }});
268
269 awaitTermination(t);
270 }
271
272 /**
273 * getBlocker(null) throws NullPointerException
274 */
275 public void testGetBlockerNull() {
276 try {
277 LockSupport.getBlocker(null);
278 shouldThrow();
279 } catch (NullPointerException success) {}
280 }
281
282 /**
283 * getBlocker returns the blocker object passed to park
284 */
285 public void testGetBlocker_parkBlocker() {
286 testGetBlocker(ParkMethod.parkBlocker);
287 }
288 public void testGetBlocker_parkNanosBlocker() {
289 testGetBlocker(ParkMethod.parkNanosBlocker);
290 }
291 public void testGetBlocker_parkUntilBlocker() {
292 testGetBlocker(ParkMethod.parkUntilBlocker);
293 }
294 public void testGetBlocker(final ParkMethod parkMethod) {
295 final CountDownLatch started = new CountDownLatch(1);
296 Thread t = newStartedThread(new CheckedRunnable() {
297 public void realRun() {
298 Thread t = Thread.currentThread();
299 started.countDown();
300 do {
301 assertNull(LockSupport.getBlocker(t));
302 parkMethod.park();
303 assertNull(LockSupport.getBlocker(t));
304 // park may return spuriously
305 } while (! Thread.currentThread().isInterrupted());
306 }});
307
308 long startTime = System.nanoTime();
309 await(started);
310 for (;;) {
311 Object x = LockSupport.getBlocker(t);
312 if (x == theBlocker()) { // success
313 t.interrupt();
314 awaitTermination(t);
315 assertNull(LockSupport.getBlocker(t));
316 return;
317 } else {
318 assertNull(x); // ok
319 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
320 fail("timed out");
321 Thread.yield();
322 }
323 }
324 }
325
326 /**
327 * timed park(0) returns immediately.
328 *
329 * Requires hotspot fix for:
330 * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever
331 * which is in jdk7-b118 and 6u25.
332 */
333 public void testPark0_parkNanos() {
334 testPark0(ParkMethod.parkNanos);
335 }
336 public void testPark0_parkUntil() {
337 testPark0(ParkMethod.parkUntil);
338 }
339 public void testPark0_parkNanosBlocker() {
340 testPark0(ParkMethod.parkNanosBlocker);
341 }
342 public void testPark0_parkUntilBlocker() {
343 testPark0(ParkMethod.parkUntilBlocker);
344 }
345 public void testPark0(final ParkMethod parkMethod) {
346 Thread t = newStartedThread(new CheckedRunnable() {
347 public void realRun() {
348 parkMethod.park(0L);
349 }});
350
351 awaitTermination(t);
352 }
353
354 /**
355 * timed park(Long.MIN_VALUE) returns immediately.
356 */
357 public void testParkNeg_parkNanos() {
358 testParkNeg(ParkMethod.parkNanos);
359 }
360 public void testParkNeg_parkUntil() {
361 testParkNeg(ParkMethod.parkUntil);
362 }
363 public void testParkNeg_parkNanosBlocker() {
364 testParkNeg(ParkMethod.parkNanosBlocker);
365 }
366 public void testParkNeg_parkUntilBlocker() {
367 testParkNeg(ParkMethod.parkUntilBlocker);
368 }
369 public void testParkNeg(final ParkMethod parkMethod) {
370 Thread t = newStartedThread(new CheckedRunnable() {
371 public void realRun() {
372 parkMethod.park(Long.MIN_VALUE);
373 }});
374
375 awaitTermination(t);
376 }
377 }