ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/locks/LockSupport.java
Revision: 1.2
Committed: Thu Jun 15 22:48:08 2017 UTC (6 years, 11 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +2 -0 lines
Log Message:
8181082: class-level since tag issues in java.base & java.datatransfer module

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7 package java.util.concurrent.locks;
8
9 /**
10 * Basic thread blocking primitives for creating locks and other
11 * synchronization classes.
12 *
13 * <p>This class associates, with each thread that uses it, a permit
14 * (in the sense of the {@link java.util.concurrent.Semaphore
15 * Semaphore} class). A call to {@code park} will return immediately
16 * if the permit is available, consuming it in the process; otherwise
17 * it <em>may</em> block. A call to {@code unpark} makes the permit
18 * available, if it was not already available. (Unlike with Semaphores
19 * though, permits do not accumulate. There is at most one.)
20 * Reliable usage requires the use of volatile (or atomic) variables
21 * to control when to park or unpark. Orderings of calls to these
22 * methods are maintained with respect to volatile variable accesses,
23 * but not necessarily non-volatile variable accesses.
24 *
25 * <p>Methods {@code park} and {@code unpark} provide efficient
26 * means of blocking and unblocking threads that do not encounter the
27 * problems that cause the deprecated methods {@code Thread.suspend}
28 * and {@code Thread.resume} to be unusable for such purposes: Races
29 * between one thread invoking {@code park} and another thread trying
30 * to {@code unpark} it will preserve liveness, due to the
31 * permit. Additionally, {@code park} will return if the caller's
32 * thread was interrupted, and timeout versions are supported. The
33 * {@code park} method may also return at any other time, for "no
34 * reason", so in general must be invoked within a loop that rechecks
35 * conditions upon return. In this sense {@code park} serves as an
36 * optimization of a "busy wait" that does not waste as much time
37 * spinning, but must be paired with an {@code unpark} to be
38 * effective.
39 *
40 * <p>The three forms of {@code park} each also support a
41 * {@code blocker} object parameter. This object is recorded while
42 * the thread is blocked to permit monitoring and diagnostic tools to
43 * identify the reasons that threads are blocked. (Such tools may
44 * access blockers using method {@link #getBlocker(Thread)}.)
45 * The use of these forms rather than the original forms without this
46 * parameter is strongly encouraged. The normal argument to supply as
47 * a {@code blocker} within a lock implementation is {@code this}.
48 *
49 * <p>These methods are designed to be used as tools for creating
50 * higher-level synchronization utilities, and are not in themselves
51 * useful for most concurrency control applications. The {@code park}
52 * method is designed for use only in constructions of the form:
53 *
54 * <pre> {@code
55 * while (!canProceed()) {
56 * // ensure request to unpark is visible to other threads
57 * ...
58 * LockSupport.park(this);
59 * }}</pre>
60 *
61 * where no actions by the thread publishing a request to unpark,
62 * prior to the call to {@code park}, entail locking or blocking.
63 * Because only one permit is associated with each thread, any
64 * intermediary uses of {@code park}, including implicitly via class
65 * loading, could lead to an unresponsive thread (a "lost unpark").
66 *
67 * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
68 * non-reentrant lock class:
69 * <pre> {@code
70 * class FIFOMutex {
71 * private final AtomicBoolean locked = new AtomicBoolean(false);
72 * private final Queue<Thread> waiters
73 * = new ConcurrentLinkedQueue<>();
74 *
75 * public void lock() {
76 * boolean wasInterrupted = false;
77 * // publish current thread for unparkers
78 * waiters.add(Thread.currentThread());
79 *
80 * // Block while not first in queue or cannot acquire lock
81 * while (waiters.peek() != Thread.currentThread() ||
82 * !locked.compareAndSet(false, true)) {
83 * LockSupport.park(this);
84 * // ignore interrupts while waiting
85 * if (Thread.interrupted())
86 * wasInterrupted = true;
87 * }
88 *
89 * waiters.remove();
90 * // ensure correct interrupt status on return
91 * if (wasInterrupted)
92 * Thread.currentThread().interrupt();
93 * }
94 *
95 * public void unlock() {
96 * locked.set(false);
97 * LockSupport.unpark(waiters.peek());
98 * }
99 *
100 * static {
101 * // Reduce the risk of "lost unpark" due to classloading
102 * Class<?> ensureLoaded = LockSupport.class;
103 * }
104 * }}</pre>
105 *
106 * @since 1.5
107 */
108 public class LockSupport {
109 private LockSupport() {} // Cannot be instantiated.
110
111 private static void setBlocker(Thread t, Object arg) {
112 // Even though volatile, hotspot doesn't need a write barrier here.
113 U.putObject(t, PARKBLOCKER, arg);
114 }
115
116 /**
117 * Makes available the permit for the given thread, if it
118 * was not already available. If the thread was blocked on
119 * {@code park} then it will unblock. Otherwise, its next call
120 * to {@code park} is guaranteed not to block. This operation
121 * is not guaranteed to have any effect at all if the given
122 * thread has not been started.
123 *
124 * @param thread the thread to unpark, or {@code null}, in which case
125 * this operation has no effect
126 */
127 public static void unpark(Thread thread) {
128 if (thread != null)
129 U.unpark(thread);
130 }
131
132 /**
133 * Disables the current thread for thread scheduling purposes unless the
134 * permit is available.
135 *
136 * <p>If the permit is available then it is consumed and the call returns
137 * immediately; otherwise
138 * the current thread becomes disabled for thread scheduling
139 * purposes and lies dormant until one of three things happens:
140 *
141 * <ul>
142 * <li>Some other thread invokes {@link #unpark unpark} with the
143 * current thread as the target; or
144 *
145 * <li>Some other thread {@linkplain Thread#interrupt interrupts}
146 * the current thread; or
147 *
148 * <li>The call spuriously (that is, for no reason) returns.
149 * </ul>
150 *
151 * <p>This method does <em>not</em> report which of these caused the
152 * method to return. Callers should re-check the conditions which caused
153 * the thread to park in the first place. Callers may also determine,
154 * for example, the interrupt status of the thread upon return.
155 *
156 * @param blocker the synchronization object responsible for this
157 * thread parking
158 * @since 1.6
159 */
160 public static void park(Object blocker) {
161 Thread t = Thread.currentThread();
162 setBlocker(t, blocker);
163 U.park(false, 0L);
164 setBlocker(t, null);
165 }
166
167 /**
168 * Disables the current thread for thread scheduling purposes, for up to
169 * the specified waiting time, unless the permit is available.
170 *
171 * <p>If the permit is available then it is consumed and the call
172 * returns immediately; otherwise the current thread becomes disabled
173 * for thread scheduling purposes and lies dormant until one of four
174 * things happens:
175 *
176 * <ul>
177 * <li>Some other thread invokes {@link #unpark unpark} with the
178 * current thread as the target; or
179 *
180 * <li>Some other thread {@linkplain Thread#interrupt interrupts}
181 * the current thread; or
182 *
183 * <li>The specified waiting time elapses; or
184 *
185 * <li>The call spuriously (that is, for no reason) returns.
186 * </ul>
187 *
188 * <p>This method does <em>not</em> report which of these caused the
189 * method to return. Callers should re-check the conditions which caused
190 * the thread to park in the first place. Callers may also determine,
191 * for example, the interrupt status of the thread, or the elapsed time
192 * upon return.
193 *
194 * @param blocker the synchronization object responsible for this
195 * thread parking
196 * @param nanos the maximum number of nanoseconds to wait
197 * @since 1.6
198 */
199 public static void parkNanos(Object blocker, long nanos) {
200 if (nanos > 0) {
201 Thread t = Thread.currentThread();
202 setBlocker(t, blocker);
203 U.park(false, nanos);
204 setBlocker(t, null);
205 }
206 }
207
208 /**
209 * Disables the current thread for thread scheduling purposes, until
210 * the specified deadline, unless the permit is available.
211 *
212 * <p>If the permit is available then it is consumed and the call
213 * returns immediately; otherwise the current thread becomes disabled
214 * for thread scheduling purposes and lies dormant until one of four
215 * things happens:
216 *
217 * <ul>
218 * <li>Some other thread invokes {@link #unpark unpark} with the
219 * current thread as the target; or
220 *
221 * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
222 * current thread; or
223 *
224 * <li>The specified deadline passes; or
225 *
226 * <li>The call spuriously (that is, for no reason) returns.
227 * </ul>
228 *
229 * <p>This method does <em>not</em> report which of these caused the
230 * method to return. Callers should re-check the conditions which caused
231 * the thread to park in the first place. Callers may also determine,
232 * for example, the interrupt status of the thread, or the current time
233 * upon return.
234 *
235 * @param blocker the synchronization object responsible for this
236 * thread parking
237 * @param deadline the absolute time, in milliseconds from the Epoch,
238 * to wait until
239 * @since 1.6
240 */
241 public static void parkUntil(Object blocker, long deadline) {
242 Thread t = Thread.currentThread();
243 setBlocker(t, blocker);
244 U.park(true, deadline);
245 setBlocker(t, null);
246 }
247
248 /**
249 * Returns the blocker object supplied to the most recent
250 * invocation of a park method that has not yet unblocked, or null
251 * if not blocked. The value returned is just a momentary
252 * snapshot -- the thread may have since unblocked or blocked on a
253 * different blocker object.
254 *
255 * @param t the thread
256 * @return the blocker
257 * @throws NullPointerException if argument is null
258 * @since 1.6
259 */
260 public static Object getBlocker(Thread t) {
261 if (t == null)
262 throw new NullPointerException();
263 return U.getObjectVolatile(t, PARKBLOCKER);
264 }
265
266 /**
267 * Disables the current thread for thread scheduling purposes unless the
268 * permit is available.
269 *
270 * <p>If the permit is available then it is consumed and the call
271 * returns immediately; otherwise the current thread becomes disabled
272 * for thread scheduling purposes and lies dormant until one of three
273 * things happens:
274 *
275 * <ul>
276 *
277 * <li>Some other thread invokes {@link #unpark unpark} with the
278 * current thread as the target; or
279 *
280 * <li>Some other thread {@linkplain Thread#interrupt interrupts}
281 * the current thread; or
282 *
283 * <li>The call spuriously (that is, for no reason) returns.
284 * </ul>
285 *
286 * <p>This method does <em>not</em> report which of these caused the
287 * method to return. Callers should re-check the conditions which caused
288 * the thread to park in the first place. Callers may also determine,
289 * for example, the interrupt status of the thread upon return.
290 */
291 public static void park() {
292 U.park(false, 0L);
293 }
294
295 /**
296 * Disables the current thread for thread scheduling purposes, for up to
297 * the specified waiting time, unless the permit is available.
298 *
299 * <p>If the permit is available then it is consumed and the call
300 * returns immediately; otherwise the current thread becomes disabled
301 * for thread scheduling purposes and lies dormant until one of four
302 * things happens:
303 *
304 * <ul>
305 * <li>Some other thread invokes {@link #unpark unpark} with the
306 * current thread as the target; or
307 *
308 * <li>Some other thread {@linkplain Thread#interrupt interrupts}
309 * the current thread; or
310 *
311 * <li>The specified waiting time elapses; or
312 *
313 * <li>The call spuriously (that is, for no reason) returns.
314 * </ul>
315 *
316 * <p>This method does <em>not</em> report which of these caused the
317 * method to return. Callers should re-check the conditions which caused
318 * the thread to park in the first place. Callers may also determine,
319 * for example, the interrupt status of the thread, or the elapsed time
320 * upon return.
321 *
322 * @param nanos the maximum number of nanoseconds to wait
323 */
324 public static void parkNanos(long nanos) {
325 if (nanos > 0)
326 U.park(false, nanos);
327 }
328
329 /**
330 * Disables the current thread for thread scheduling purposes, until
331 * the specified deadline, unless the permit is available.
332 *
333 * <p>If the permit is available then it is consumed and the call
334 * returns immediately; otherwise the current thread becomes disabled
335 * for thread scheduling purposes and lies dormant until one of four
336 * things happens:
337 *
338 * <ul>
339 * <li>Some other thread invokes {@link #unpark unpark} with the
340 * current thread as the target; or
341 *
342 * <li>Some other thread {@linkplain Thread#interrupt interrupts}
343 * the current thread; or
344 *
345 * <li>The specified deadline passes; or
346 *
347 * <li>The call spuriously (that is, for no reason) returns.
348 * </ul>
349 *
350 * <p>This method does <em>not</em> report which of these caused the
351 * method to return. Callers should re-check the conditions which caused
352 * the thread to park in the first place. Callers may also determine,
353 * for example, the interrupt status of the thread, or the current time
354 * upon return.
355 *
356 * @param deadline the absolute time, in milliseconds from the Epoch,
357 * to wait until
358 */
359 public static void parkUntil(long deadline) {
360 U.park(true, deadline);
361 }
362
363 /**
364 * Returns the pseudo-randomly initialized or updated secondary seed.
365 * Copied from ThreadLocalRandom due to package access restrictions.
366 */
367 static final int nextSecondarySeed() {
368 int r;
369 Thread t = Thread.currentThread();
370 if ((r = U.getInt(t, SECONDARY)) != 0) {
371 r ^= r << 13; // xorshift
372 r ^= r >>> 17;
373 r ^= r << 5;
374 }
375 else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
376 r = 1; // avoid zero
377 U.putInt(t, SECONDARY, r);
378 return r;
379 }
380
381 // Hotspot implementation via intrinsics API
382 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
383 private static final long PARKBLOCKER;
384 private static final long SECONDARY;
385 static {
386 try {
387 PARKBLOCKER = U.objectFieldOffset
388 (Thread.class.getDeclaredField("parkBlocker"));
389 SECONDARY = U.objectFieldOffset
390 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
391 } catch (ReflectiveOperationException e) {
392 throw new Error(e);
393 }
394 }
395
396 }