【问题标题】:Does a thread release a lock when it finishes?线程完成时是否释放锁?
【发布时间】:2015-10-11 11:43:11
【问题描述】:

我在某些地方读到过,获取Lock 对象而不将其后的代码包含在try...finally 块中是不好的编程习惯,因此即使抛出异常也可以释放锁。

这听起来像是一个简单的问题:线程完成时是否所有属于线程的锁都会自动释放?

我问这个问题的原因是我正在处理的程序是这样的,一旦一个线程获得一个锁,它应该没有理由让它离开,直到它完成。此外,我是使用锁的新手,所以我想知道是否有任何我可能没有考虑过的陷阱。我是否必须担心在线程完成之前显式释放我的代码中的锁,或者我是否可以将其留给 JVM,确信知道所有活动线程的锁上被阻塞的其他线程将在活动线程中被激活线程停止了吗?

【问题讨论】:

  • 请贴一些代码。
  • @C1sc0:一些关于什么的代码?这个问题有一个非常明确的问题陈述
  • 你可以用一个非常简单的应用程序来测试它。创建两个线程,尝试获取相同的锁,然后直接杀死线程。如果第二个线程获得了锁,它确实被解锁了。
  • 这取决于锁的实现,但一般不会。
  • @Patrick 我知道我有点懒……我猜我的方式……我想我可以继续假设锁是自动释放的,看看我的程序如何应对.. .

标签: java multithreading


【解决方案1】:

简单的测试可能会告诉你在线程终止时锁没有被释放:

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

所以当单独的线程获得锁,然后退出时,主线程无法获得锁。

【讨论】:

  • 最好将特定线程获取的锁与该线程相关联——API(有点令人惊讶)似乎没有这样做。我想可以在自定义线程实现中保存一组获取的锁,并在线程即将完成之前将它们全部释放。不知道有没有坑...
  • @OwenThomas,API 确实将锁与线程相关联。你可以检查这个尝试从另一个线程解锁获得的锁:你会得到一个异常。在线程完成后添加自动解锁是太多不必要的工作和不必要的开销。
  • 有没有我可以在当前线程上调用的方法——比如 getLocks()——返回一个包含线程锁的集合?
  • @OwenThomas,好吧,您可以使用 ManagementFactory.getThreadMXBean( ).getThreadInfo(..).getLockedMonitors(..) 之类的东西来执行此操作,但您不会有 Lock 对象本身,而是线程使用的原始监视器。
  • 嗯...看起来有点笨拙...您对在 Thread 的子类(或 Runnable 或 Callable 的实现)中包含这样的集合是否有效有意见吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多