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 |
} |