在Java中使用Thread对象的内部锁是否可以?

时间:2016-08-22 15:42:17

标签: 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完成/退出之前,这似乎最终导致其他一些线程不必要地(甚至危险地)阻塞。
  3. 以上是否有效?我觉得我需要Brian Goetz这个灯塔: - )

1 个答案:

答案 0 :(得分:2)

  

...有没有理由避免[锁定Thread个实例]?

因此,如果查看Thread类,可以看到有许多实例synchronized方法。它们包括:

  • start()
  • stop()(已弃用)
  • join(long)(来自join()
  • join(long, int)
  

Bar完成/退出之前,似乎最终可能会导致某些其他线程不必要地(甚至危险地)阻塞。

是的,所以调用上述方法的任何人都会阻止其他synchronized方法。显然,只有join(...)方法确实存在问题,并且无论如何都应该返回Thread

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

  

当一个线程终止   调用this.notifyAll()方法。建议这样做   应用程序不使用wait()notify()或   notifyAll()个实例Thread

我在synchronized来源的任何地方都看不到关于Thread的警告。

同样快速浏览ThreadPoolExecutor表明它至少在synchronizeRunnable个实例上没有Callable,这样会非常糟糕,所以至少标准的ExecutorService你应该是好的。

所以我想简短的回答是,虽然可能不推荐,但在Thread上进行同步时应该有效。正如您所提到的,最好是实施Runnable并锁定它而不是扩展Thread

希望这有帮助。