LockSupport.java 中的 FIFO 互斥代码片段
Posted
技术标签:
【中文标题】LockSupport.java 中的 FIFO 互斥代码片段【英文标题】:FIFO mutex code snippet in LockSupport.java 【发布时间】:2020-06-15 20:36:28 【问题描述】:我试图了解LockSupport.java
并参考了它的文档。在那里,它有代码 sn-p,其中作者提供了使用 LockSupport#park() 和 LockSupport#Unpark() 实现互斥锁的示例。
我使用该示例并创建了一个使用该示例 FIFOMutex 的程序。
FIFOMutex 代码(取自 LockSupport.java)
package com.example.java.locking.studies.locksupport.from.javadoc;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
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);
if (Thread.interrupted()) // ignore interrupts while waiting
wasInterrupted = true;
waiters.remove();
if (wasInterrupted) // reassert interrupt status on exit
current.interrupt();
public void unlock()
locked.set(false);
LockSupport.unpark(waiters.peek());
现在,我编写了下面的程序来使用FIFOMutex作为锁定机制,代码如下:
package com.example.java.locking.studies.locksupport.from.javadoc;
public class FIFOMutexMainApp
public static void main(String[] args) throws InterruptedException
FIFOMutex mutex = new FIFOMutex();
Thread t1 = new Thread(new Runnable()
@Override
public void run()
System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");
mutex.lock();
System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");
for (;;)
);
Thread t2 = new Thread(new Runnable()
@Override
public void run()
System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");
mutex.unlock();
System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");
for (;;)
);
t1.start();
Thread.sleep(10);
t2.start();
Thread.sleep(100);
mutex.lock();
System.out.println("Inside thread -> " + Thread.currentThread() + "will I get printed?");
下面是这个程序的输出:
Inside thread -> Thread[Thread-0,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-0,5,main]After mutex.lock()
Inside thread -> Thread[Thread-1,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-1,5,main]After mutex.lock()
Inside thread -> Thread[main,5,main]will I get printed?
Thread-1 启动并获取锁,随后是调用 unlock() 的 Thread-2。主要调用 lock()。我的理解是 Main 将永远被阻塞,即使 Thread-2 调用了 unlock(),因为 Thread-2 从未调用 lock()(因此,它从未被授予 permit
)。
我无法理解这种行为。如果我在 Thread-2 中注释 unlock(),那么主线程将永远被阻塞。
一个线程(在我的情况下是 Thread-2)怎么可能调用 unlock()(以前没有调用 lock())而其他线程(在这种情况下是主线程)调用 lock(),但从来没有被锁了?
【问题讨论】:
【参考方案1】:如果你深入源码,unblock 方法实际上是释放变量locked
提供的 CAS 锁,并 unpark 第一个线程。所以如果注释掉unlock()
的调用,CAS锁不会被释放,主线程可以永远停留在while循环中,从而阻塞主线程。
【讨论】:
【参考方案2】:首先:FIFOMutex 调用
Thread current = Thread.currentThread();
意味着实际线程被用于验证。这意味着考虑了最实际的线程,即:
线程 1 首先发出锁,然后 线程 2 被调用并发出解锁。这就是主线程不会挂起的原因。 但是:如果您评论线程 2 的解锁,则没有完成并且主线程挂起。这很好理解,不是吗?
【讨论】:
以上是关于LockSupport.java 中的 FIFO 互斥代码片段的主要内容,如果未能解决你的问题,请参考以下文章