当前位置: 代码迷 >> 综合 >> JUC锁——LockSupport
  详细解决方案

JUC锁——LockSupport

热度:42   发布时间:2023-12-22 03:43:35.0
LockSupport介绍

??LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到Thread.suspend 和 Thread.resume所可能引发的死锁问题。因为park() 和 unpark()有许可的存在,调用 park() 的线程和另一个试图将其 unpark() 的线程之间的竞争将保持活性。

LockSupport方法列表
// 返回提供给最近一次尚未解除阻塞的park方法调用的blocker对象,如果该调用不受阻塞,则返回 null
static Object getBlocker(Thread t)
// 为了线程调度,禁用当前线程,除非许可可用
static void park()
// 为了线程调度,在许可可用之前禁用当前线程
static void park(Object blocker)
// 为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用
static void parkNanos(long nanos)
// 为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间
static void parkNanos(Object blocker, long nanos)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用
static void parkUntil(long deadline)
// 为了线程调度,在指定的时限前禁用当前线程,除非许可可用
static void parkUntil(Object blocker, long deadline)
// 如果给定线程的许可尚不可用,则使其可用
static void unpark(Thread thread)
LockSupport源码
public class LockSupport {
    private LockSupport() {
    } // Cannot be instantiated.// Hotspot implementation via intrinsics APIprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long parkBlockerOffset;static {
    try {
    parkBlockerOffset = unsafe.objectFieldOffset(java.lang.Thread.class.getDeclaredField("parkBlocker"));} catch (Exception ex) {
     throw new Error(ex); }}private static void setBlocker(Thread t, Object arg) {
    // Even though volatile, hotspot doesn't need a write barrier here.unsafe.putObject(t, parkBlockerOffset, arg);}/*** Makes available the permit for the given thread, if it* was not already available. If the thread was blocked on* {@code park} then it will unblock. Otherwise, its next call* to {@code park} is guaranteed not to block. This operation* is not guaranteed to have any effect at all if the given* thread has not been started.** @param thread the thread to unpark, or {@code null}, in which case* this operation has no effect*/public static void unpark(Thread thread) {
    if (thread != null)unsafe.unpark(thread);}/*** Disables the current thread for thread scheduling purposes unless the* permit is available.** <p>If the permit is available then it is consumed and the call returns* immediately; otherwise* the current thread becomes disabled for thread scheduling* purposes and lies dormant until one of three things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread upon return.** @param blocker the synchronization object responsible for this* thread parking* @since 1.6*/public static void park(Object blocker) {
    Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(false, 0L);setBlocker(t, null);}/*** Disables the current thread for thread scheduling purposes, for up to* the specified waiting time, unless the permit is available.** <p>If the permit is available then it is consumed and the call* returns immediately; otherwise the current thread becomes disabled* for thread scheduling purposes and lies dormant until one of four* things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The specified waiting time elapses; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread, or the elapsed time* upon return.** @param blocker the synchronization object responsible for this* thread parking* @param nanos the maximum number of nanoseconds to wait* @since 1.6*/public static void parkNanos(Object blocker, long nanos) {
    if (nanos > 0) {
    Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(false, nanos);setBlocker(t, null);}}/*** Disables the current thread for thread scheduling purposes, until* the specified deadline, unless the permit is available.** <p>If the permit is available then it is consumed and the call* returns immediately; otherwise the current thread becomes disabled* for thread scheduling purposes and lies dormant until one of four* things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts} the* current thread; or** <li>The specified deadline passes; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread, or the current time* upon return.** @param blocker the synchronization object responsible for this* thread parking* @param deadline the absolute time, in milliseconds from the Epoch,* to wait until* @since 1.6*/public static void parkUntil(Object blocker, long deadline) {
    Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(true, deadline);setBlocker(t, null);}/*** Returns the blocker object supplied to the most recent* invocation of a park method that has not yet unblocked, or null* if not blocked. The value returned is just a momentary* snapshot -- the thread may have since unblocked or blocked on a* different blocker object.** @param t the thread* @return the blocker* @throws NullPointerException if argument is null* @since 1.6*/public static Object getBlocker(Thread t) {
    if (t == null)throw new NullPointerException();return unsafe.getObjectVolatile(t, parkBlockerOffset);}/*** Disables the current thread for thread scheduling purposes unless the* permit is available.** <p>If the permit is available then it is consumed and the call* returns immediately; otherwise the current thread becomes disabled* for thread scheduling purposes and lies dormant until one of three* things happens:** <ul>** <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread upon return.*/public static void park() {
    unsafe.park(false, 0L);}/*** Disables the current thread for thread scheduling purposes, for up to* the specified waiting time, unless the permit is available.** <p>If the permit is available then it is consumed and the call* returns immediately; otherwise the current thread becomes disabled* for thread scheduling purposes and lies dormant until one of four* things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The specified waiting time elapses; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread, or the elapsed time* upon return.** @param nanos the maximum number of nanoseconds to wait*/public static void parkNanos(long nanos) {
    if (nanos > 0)unsafe.park(false, nanos);}/*** Disables the current thread for thread scheduling purposes, until* the specified deadline, unless the permit is available.** <p>If the permit is available then it is consumed and the call* returns immediately; otherwise the current thread becomes disabled* for thread scheduling purposes and lies dormant until one of four* things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The specified deadline passes; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread, or the current time* upon return.** @param deadline the absolute time, in milliseconds from the Epoch,* to wait until*/public static void parkUntil(long deadline) {
    unsafe.park(true, deadline);}
}

说明:LockSupport是通过调用Unsafe函数中的接口实现阻塞和解除阻塞的

LockSupport示例

示例1:

public class WaitTest1 {
    public static void main(String args[]) {
    ThreadA ta = new ThreadA("ta");synchronized (ta) {
    try {
    System.out.println(Thread.currentThread().getName() + " start ta.");ta.start();Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + " block.");ta.wait();System.out.println(Thread.currentThread().getName() + " continue.");} catch (InterruptedException e) {
    e.printStackTrace();}}}static class ThreadA extends Thread {
    public ThreadA(String name) {
    super(name);}public void run() {
    synchronized (this) {
    System.out.println(Thread.currentThread().getName() + " wake up others.");notify();}}}
}//结果
main start ta.
main block.
ta wake up others.
main continue.

示例2:

public class LockSupportTest2 {
    private static Thread mainThread;public static void main(String args) {
    ThreadA ta = new ThreadA("ta");mainThread = Thread.currentThread();System.out.println(Thread.currentThread().getName() + " start ta.");ta.start();System.out.println(Thread.currentThread().getName() + " block.");LockSupport.park(mainThread);System.out.println(Thread.currentThread().getName() + " continue.");}static class ThreadA extends Thread {
    public ThreadA(String name) {
    super(name);}public void run() {
    System.out.println(Thread.currentThread().getName() + " wake up others.");LockSupport.unpark(mainThread);}}
}//结果
main start ta.
main block.
ta wake up others.
main continue.

说明:park和wait的区别——wait让线程阻塞前,必须先通过synchronized获取同步锁(即调用某个对象的wait()阻塞某个线程时必须保证该线程持有该对象为锁);park不需要获取同步锁,而且可以指定需要阻塞的线程