JUC.LockSupport

    1173
    最后修改于

    本文是对 JUC 包中的 LockSupport 类说明的翻译。很好的解释了 LockSupport 是什么。

    LockSupport 提供基本的线程阻塞原语,用于创建锁和其他同步类。

    每个线程都关联到一个许可证(也就是 Semaphore 类中的许可概念。译注:这里的 permit 许可也就是 Semaphore 信号量,想起来你在 OS 课上接触到的信号量了吗?😄)。与 Semaphore 不同的是,每个线程最多只有一个许可(信号量最大值为 1)。调用 park 时,如果许可证可用,将立即返回,同时消耗该许可证(信号量 - 1);否则可能会阻塞。调用 unpark 则让使许可证可用(也就是让信号量 = 1)。
    loading...

    Basic thread blocking primitives for creating locks and other synchronization classes.
    This class associates, with each thread that uses it, a permit (in the sense of the Semaphore class). A call to park will return immediately if the permit is available, consuming it in the process; otherwise it may block. A call to unpark makes the permit available, if it was not already available. (Unlike with Semaphores though, permits do not accumulate. There is at most one.)

    parkunpark方法提供了高效的线程阻塞和恢复方式,避免了Thread.suspendThread.resume方法(已标记为弃用)可能导致的各种问题:
    由于许可证的存在,即使在出现「一个线程调用park时,另一个线程也正尝试unpark该线程」竞态条件时,调用 park 的线程也还可以正常执行。
    如果线程调用park后,被中断,park 将返回,线程可以继续执行。
    park支持超时机制。
    值得注意的是 park 方法可能 “无缘无故的” 返回,因此通常必须在重新检查条件的循环内调用它。从这个角度来看,park 是作为 “忙等待” 的一种优化,不会浪费太多时间在自旋上。但必须与unpark 配和才能有效。

    Methods park and unpark provide efficient means of blocking and unblocking threads that do not encounter the problems that cause the deprecated methods Thread.suspend and Thread.resume to be unusable for such purposes:
    Races between one thread invoking park and another thread trying to unpark it will preserve liveness, due to the permit.

    Additionally, park will return if the caller's thread was interrupted, and timeout versions are supported.

    The park method may also return at any other time, for "no reason", so in general must be invoked within a loop that rechecks conditions upon return. In this sense park serves as an optimization of a "busy wait" that does not waste as much time spinning, but must be paired with an unpark to be effective.

    park 的三种形式都支持传入一个名为阻塞者对象的参数,该对象在线程被阻塞时记录下来,这样监视和诊断工具可以方便的识别线程被阻塞的原因(调用 getBlocker(Thread))。
    强烈建议调用带阻塞者对象的版本,而非无参版本。在锁实现中,调用park时通常传入的阻塞者对象是this

    The three forms of park each also support a blocker object parameter. This object is recorded while the thread is blocked to permit monitoring and diagnostic tools to identify the reasons that threads are blocked.
    (Such tools may access blockers using method getBlocker(Thread).)
    The use of these forms rather than the original forms without this parameter is strongly encouraged.
    The normal argument to supply as a blocker within a lock implementation is this.

    LockSupport中的这些方法的设计目的是为更高级的同步工具提供帮助,对于大多数需要并发控制应用来说,不需要这么底层的工具。park 方法设计用于如下形式的场景:

    These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in themselves useful for most concurrency control applications.
    The park method is designed for use only in constructions of the form:

    while (!canProceed()) { ... LockSupport. park(this); }
    

    其中,canProceed 以及调用 park 之前的任何其他操作都不会导致线程锁定或阻塞。由于每个线程只关联到一个许可证,因此 park 的任何中间使用都可能干扰其预期效果。
    示例用法。下面是一个不可重入的 FIFO 锁类 demo:

    where neither canProceed nor any other actions prior to the call to park entail locking or blocking. Because only one permit is associated with each thread, any intermediary uses of park could interfere with its intended effects.
    Sample Usage. Here is a sketch of a first-in-first-out non-reentrant lock class:

    class FIFOMutex {
    	private final AtomicBoolean locked = new AtomicBoolean(false);
        private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
    
    	public void lock() {
    	    boolean wasInterrupted = false;
    		Thread current = Thread. currentThread();
    		waiters.add(current);
    		// Block while not first in queue or cannot acquire lock
    		// 当前线程不在队首或者拿不到锁
    		while (waiters. peek() != current || 
    		!locked. compareAndSet(false, true)) {
    		    LockSupport. park(this);
    		    // 在等待时,忽略线程中断 ignore interrupts while waiting
    			if (Thread.interrupted())
    				wasInterrupted = true;
    		 }
    		waiters.remove();
    		//在退出时重新验证是否中断 reassert interrupt status on exit
    		if (wasInterrupted) current.interrupt();
       }
    	
    	public void unlock() {
    		locked. set(false);
    		LockSupport.unpark(waiters.peek());
    	}
    }
    
    • 🥳0
    • 👍0
    • 💩0
    • 🤩0
    总浏览量 4,355