1. /*
  2. * @(#)LockSupport.java 1.6 04/01/24
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent.locks;
  8. import java.util.concurrent.*;
  9. import sun.misc.Unsafe;
  10. /**
  11. * Basic thread blocking primitives for creating locks and other
  12. * synchronization classes.
  13. *
  14. * <p>This class associates with each thread that uses it, a permit
  15. * (in the sense of the {@link java.util.concurrent.Semaphore
  16. * Semaphore} class). A call to <tt>park</tt> will return immediately
  17. * if the permit is available, consuming it in the process; otherwise
  18. * it <em>may</em> block. A call to <tt>unpark</tt> makes the permit
  19. * available, if it was not already available. (Unlike with Semaphores
  20. * though, permits do not accumulate. There is at most one.)
  21. *
  22. * <p>Methods <tt>park</tt> and <tt>unpark</tt> provide efficient
  23. * means of blocking and unblocking threads that do not encounter the
  24. * problems that cause the deprecated methods <tt>Thread.suspend</tt>
  25. * and <tt>Thread.resume</tt> to be unusable for such purposes: Races
  26. * between one thread invoking <tt>park</tt> and another thread trying
  27. * to <tt>unpark</tt> it will preserve liveness, due to the
  28. * permit. Additionally, <tt>park</tt> will return if the caller's
  29. * thread was interrupted, and timeout versions are supported. The
  30. * <tt>park</tt> method may also return at any other time, for "no
  31. * reason", so in general must be invoked within a loop that rechecks
  32. * conditions upon return. In this sense <tt>park</tt> serves as an
  33. * optimization of a "busy wait" that does not waste as much time
  34. * spinning, but must be paired with an <tt>unpark</tt> to be
  35. * effective.
  36. *
  37. * <p>These methods are designed to be used as tools for creating
  38. * higher-level synchronization utilities, and are not in themselves
  39. * useful for most concurrency control applications.
  40. *
  41. * <p><b>Sample Usage.</b> Here is a sketch of a First-in-first-out
  42. * non-reentrant lock class.
  43. * <pre>
  44. * class FIFOMutex {
  45. * private AtomicBoolean locked = new AtomicBoolean(false);
  46. * private Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
  47. *
  48. * public void lock() {
  49. * boolean wasInterrupted = false;
  50. * Thread current = Thread.currentThread();
  51. * waiters.add(current);
  52. *
  53. * // Block while not first in queue or cannot acquire lock
  54. * while (waiters.peek() != current ||
  55. * !locked.compareAndSet(false, true)) {
  56. * LockSupport.park();
  57. * if (Thread.interrupted()) // ignore interrupts while waiting
  58. * wasInterrupted = true;
  59. * }
  60. *
  61. * waiters.remove();
  62. * if (wasInterrupted) // reassert interrupt status on exit
  63. * current.interrupt();
  64. * }
  65. *
  66. * public void unlock() {
  67. * locked.set(false);
  68. * LockSupport.unpark(waiters.peek());
  69. * }
  70. * }
  71. * </pre>
  72. */
  73. public class LockSupport {
  74. private LockSupport() {} // Cannot be instantiated.
  75. // Hotspot implementation via intrinsics API
  76. private static final Unsafe unsafe = Unsafe.getUnsafe();
  77. /**
  78. * Make available the permit for the given thread, if it
  79. * was not already available. If the thread was blocked on
  80. * <tt>park</tt> then it will unblock. Otherwise, its next call
  81. * to <tt>park</tt> is guaranteed not to block. This operation
  82. * is not guaranteed to have any effect at all if the given
  83. * thread has not been started.
  84. * @param thread the thread to unpark, or <tt>null</tt>, in which case
  85. * this operation has no effect.
  86. */
  87. public static void unpark(Thread thread) {
  88. if (thread != null)
  89. unsafe.unpark(thread);
  90. }
  91. /**
  92. * Disables the current thread for thread scheduling purposes unless the
  93. * permit is available.
  94. * <p>If the permit is available then it is consumed and the call returns
  95. * immediately; otherwise
  96. * the current thread becomes disabled for thread scheduling
  97. * purposes and lies dormant until one of three things happens:
  98. * <ul>
  99. * <li>Some other thread invokes <tt>unpark</tt> with the current thread
  100. * as the target; or
  101. * <li>Some other thread {@link Thread#interrupt interrupts} the current
  102. * thread; or
  103. * <li>The call spuriously (that is, for no reason) returns.
  104. * </ul>
  105. * <p>This method does <em>not</em> report which of these caused the
  106. * method to return. Callers should re-check the conditions which caused
  107. * the thread to park in the first place. Callers may also determine,
  108. * for example, the interrupt status of the thread upon return.
  109. */
  110. public static void park() {
  111. unsafe.park(false, 0L);
  112. }
  113. /**
  114. * Disables the current thread for thread scheduling purposes, for up to
  115. * the specified waiting time, unless the permit is available.
  116. * <p>If the permit is available then it is consumed and the call returns
  117. * immediately; otherwise
  118. * the current thread becomes disabled for thread scheduling
  119. * purposes and lies dormant until one of four things happens:
  120. * <ul>
  121. * <li>Some other thread invokes <tt>unpark</tt> with the current thread
  122. * as the target; or
  123. * <li>Some other thread {@link Thread#interrupt interrupts} the current
  124. * thread; or
  125. * <li>The specified waiting time elapses; or
  126. * <li>The call spuriously (that is, for no reason) returns.
  127. * </ul>
  128. * <p>This method does <em>not</em> report which of these caused the
  129. * method to return. Callers should re-check the conditions which caused
  130. * the thread to park in the first place. Callers may also determine,
  131. * for example, the interrupt status of the thread, or the elapsed time
  132. * upon return.
  133. *
  134. * @param nanos the maximum number of nanoseconds to wait
  135. */
  136. public static void parkNanos(long nanos) {
  137. if (nanos > 0)
  138. unsafe.park(false, nanos);
  139. }
  140. /**
  141. * Disables the current thread for thread scheduling purposes, until
  142. * the specified deadline, unless the permit is available.
  143. * <p>If the permit is available then it is consumed and the call returns
  144. * immediately; otherwise
  145. * the current thread becomes disabled for thread scheduling
  146. * purposes and lies dormant until one of four things happens:
  147. * <ul>
  148. * <li>Some other thread invokes <tt>unpark</tt> with the current thread
  149. * as the target; or
  150. * <li>Some other thread {@link Thread#interrupt interrupts} the current
  151. * thread; or
  152. * <li>The specified deadline passes; or
  153. * <li>The call spuriously (that is, for no reason) returns.
  154. * </ul>
  155. * <p>This method does <em>not</em> report which of these caused the
  156. * method to return. Callers should re-check the conditions which caused
  157. * the thread to park in the first place. Callers may also determine,
  158. * for example, the interrupt status of the thread, or the current time
  159. * upon return.
  160. *
  161. * @param deadline the absolute time, in milliseconds from the Epoch, to
  162. * wait until
  163. */
  164. public static void parkUntil(long deadline) {
  165. unsafe.park(true, deadline);
  166. }
  167. }