如何检查线程是否在同步块或方法中?

8

我的Java应用程序使用了两个线程。历史上,已经使用了同步方法和专门的锁对象。我需要知道当前线程是否拥有锁以及是通过方法还是对象实现的。我该如何做到这一点?

2个回答

21

进入同步方法时,虚拟机会在当前对象上设置一个锁。因此以下代码具有相同的效果:

synchronized void syncMethod() {
    // do something
}

void syncManually() {
    synchronized (this) {
        // do something
    }
}

这意味着同步方法与

synchronized( lock ) {
    // do something
}

在你的代码中的任何位置都可以使用Thread.holdsLock(...)来检查线程是否持有特定锁。以下是一个示例代码:

final Object lock = new Object(); 

public void lockDemo() {

    System.out.println( Thread.holdsLock(lock) );     // false
    System.out.println( Thread.holdsLock(this) );     // false

    synchronized ( lock ) { 
      System.out.println( Thread.holdsLock(lock) );   // true: locked by object
      System.out.println( Thread.holdsLock(this) );   // false
    }

    doSyncMethod();
}

public synchronized void doSyncMethod() {
    System.out.println( Thread.holdsLock(lock) );  // false
    System.out.println( Thread.holdsLock(this) );  // true: locked by synchronized method
}

自从Java 1.5版本以来,ReentrantReadWriteLock等更为复杂的锁定机制已被java.util.concurrent.locks包所支持。

它们可以提供分离的读写锁定,并提高您应用程序的性能。Oracle Java教程中的Lock Objects章节是入门的好起点。


1
如果您手动请求线程转储,JVM 将打印出每个线程的堆栈跟踪,包括哪些对象/方法被锁定或等待同步块。
您可以通过在 *nix 中向 JVM 进程发送 SIGQUIT 或在启动了 JVM 的 Windows 命令提示符窗口中键入 CTRL-Break(而不是 Ctrl-C)来手动请求线程转储。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接