java - 在Java中使用Thread对象的内在锁可以吗?

标签 java multithreading synchronized

所以在Java中我知道你可以使用所谓的对象“固有锁”来创建互斥区域以及确保内存可见性。 Java 使得通过一些语法糖隐式锁定 this 对象的内在锁变得特别容易:

public class Foo{
    public synchronized doFoo(){
        //doFoo is executed in an implicit synchronized block
        //on the 'this' object
    }
}

对于保护许多对象的成员字段,这是可以理解和接受的做法。我不知道是当被锁定的对象是Thread对象时上述是否可以。例如,是否有任何理由避免以下情况?

public class Bar extends Thread{ //notice the 'extends Thread' here
    public synchronized doBar(){
        //doBar is executed in an implicit synchronized block
        //on the 'this' object
    }
}

目前,我将坚持使用我知道更安全的方法,例如:

public class Baz extends Thread{ //notice the 'extends Thread' here
    private final Object explicitLockObject = new Object();

    public doBaz(){
        synchronized(explicitLockObject){
            //doBaz impl
        }
    }
}

对于选项 #2(Bar 示例),我的担忧有两个方面:

  1. 是否存在关于在线程本身上进行同步的现有 jvm 代码或 Java 约定可能与此类锁定策略发生冲突?
  2. 锁定this通常意味着对该对象的访问应始终受到该对象的内在锁的保护。对于 Bar 线程,这意味着我们暗示每当您触摸 Bar 线程时,您都应该在实例上进行同步。这似乎最终可能导致其他一些线程不必要地(甚至危险地)阻塞,直到 Bar 完成/退出。

上述担忧是否合理?我觉得我需要一个 Brian Goetz 信标来完成这个:-)

最佳答案

... are there any reasons to avoid [locking on a Thread instance]?

因此,如果您查看Thread 类,您会发现有许多实例synchronized 方法。它们包括:

  • 开始()
  • stop()(已弃用)
  • join(long)(从 join() 调用)
  • join(long, int)

That seems like it could end up causing some other thread to block unnecessarily (or even dangerously) until Bar completes/exits.

是的,所以任何调用上述方法的人都会被其他synchronized方法阻塞。显然,只有 join(...) 方法实际上会出现问题,并且在 Thread 完成之前它们不应该返回。

javadocs for Thread.join(...) 中所述:

As a thread terminates the this.notifyAll() method is invoked. It is recommended that applications not use wait(), notify(), or notifyAll() on Thread instances.

我在 Thread 源代码中的任何地方都没有看到有关 synchronized 的警告。

此外,快速浏览一下ThreadPoolExecutor表明它至少没有在RunnableCallable同步实例会非常糟糕,所以至少使用标准的 ExecutorService 应该会很好。

所以我想简短的答案是,尽管可能不推荐,但在紧要关头在Thread上同步应该可以。正如您所提到的,您最好实现 Runnable 并锁定它,而不是扩展 Thread 。

希望这有帮助。

关于java - 在Java中使用Thread对象的内在锁可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39083666/

相关文章:

java - 挑剔的主机(锁?)

java - 扩展类时可重入锁?

java - 抽象类数组和 oop 设计 - Java

java - 如何为 PointPlacemarks 添加图层?

python - 在单线程 Python 脚本中有一个控制台

android - SQLite 数据库中的并发性

java - 同步方法调用另一个调用 wait() 的同步方法

c# - Java 和 C# 中 double 值的低级实现

java - Android 应用程序连接到 Web 服务失败

c++ - 用于加速汇总循环的多线程 C++ 程序