ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/locks/LockSupport.java
Revision: 1.66
Committed: Fri Mar 18 16:00:16 2022 UTC (2 years, 2 months ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.65: +3 -3 lines
Log Message:
Faster queue check

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