所以在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
示例),我的担忧有两个方面:
- 是否存在关于在线程本身上进行同步的现有 jvm 代码或 Java 约定可能与此类锁定策略发生冲突?
- 锁定
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 usewait()
,notify()
, ornotifyAll()
onThread
instances.
我在 Thread
源代码中的任何地方都没有看到有关 synchronized
的警告。
此外,快速浏览一下ThreadPoolExecutor
表明它至少没有在Runnable
或Callable
上同步
实例会非常糟糕,所以至少使用标准的 ExecutorService 应该会很好。
所以我想简短的答案是,尽管可能不推荐,但在紧要关头在Thread
上同步应该可以。正如您所提到的,您最好实现 Runnable 并锁定它,而不是扩展 Thread 。
希望这有帮助。
关于java - 在Java中使用Thread对象的内在锁可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39083666/