我在某些地方读到过,获取一个Lock
对象时最好将其包含在try...finally
块中,这样即使抛出异常也可以释放锁。
可能听起来很简单的问题:所有属于线程的锁在线程完成时自动释放吗?
我问这个问题的原因是,我正在处理的程序是这样的,一旦线程获取锁,它就没有理由在完成之前释放它。此外,我刚开始使用锁,所以想知道是否有任何我尚未考虑到的陷阱。我是否需要在线程完成之前在代码中显式释放锁,还是可以将其留给JVM,在确定其他线程被阻塞在所有活动线程的锁上并且在活动线程停止后立即激活?
我在某些地方读到过,获取一个Lock
对象时最好将其包含在try...finally
块中,这样即使抛出异常也可以释放锁。
可能听起来很简单的问题:所有属于线程的锁在线程完成时自动释放吗?
我问这个问题的原因是,我正在处理的程序是这样的,一旦线程获取锁,它就没有理由在完成之前释放它。此外,我刚开始使用锁,所以想知道是否有任何我尚未考虑到的陷阱。我是否需要在线程完成之前在代码中显式释放锁,还是可以将其留给JVM,在确定其他线程被阻塞在所有活动线程的锁上并且在活动线程停止后立即激活?
简单的测试可能会显示出线程终止后锁没有释放:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
final Lock l = new ReentrantLock();
Thread t = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread()+": Acquire lock");
l.lock();
System.out.println(Thread.currentThread()+": Lock aquired: wait");
LockSupport.parkNanos(1_000_000_000);
System.out.println(Thread.currentThread()+"; Exiting");
}
};
t.start();
LockSupport.parkNanos(500_000_000);
System.out.println(Thread.currentThread()+": Acquire lock");
l.lock();
System.out.println(Thread.currentThread()+"; Success!");
}
}
输出:
Thread[Thread-0,5,main]: Acquire lock
Thread[Thread-0,5,main]: Lock aquired: wait
Thread[main,5,main]: Acquire lock
Thread[Thread-0,5,main]; Exiting
// "Success" is never written: stuck in dead-lock
因此,当单独的线程获得锁并退出时,主线程无法获取锁。
ManagementFactory.getThreadMXBean().getThreadInfo(..).getLockedMonitors(..)
的方法来实现此操作,但是你将无法获得Lock
对象本身,而是线程使用的原始监视器。 - Tagir Valeev