所以在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
示例),我的担忧是双重的:
this
通常意味着该对象的访问应该始终受到该对象的内在锁定的保护。对于Bar
线程,这意味着我们暗示每次触摸Bar
线程时,都应该在实例上进行同步。在Bar
完成/退出之前,这似乎最终导致其他一些线程不必要地(甚至危险地)阻塞。以上是否有效?我觉得我需要Brian Goetz这个灯塔: - )
答案 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
表明它至少在synchronize
或Runnable
个实例上没有Callable
,这样会非常糟糕,所以至少标准的ExecutorService
你应该是好的。
所以我想简短的回答是,虽然可能不推荐,但在Thread
上进行同步时应该有效。正如您所提到的,最好是实施Runnable
并锁定它而不是扩展Thread
。
希望这有帮助。