JUC锁——LockSupport

xiaoxiao2025-04-05  11

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 API private 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不需要获取同步锁,而且可以指定需要阻塞的线程

转载请注明原文地址: https://www.6miu.com/read-5027542.html

最新回复(0)