在java多线程中锁定"私有最终对象"有什么用?
据我的理解,我认为要使类成为线程安全的类,我们应该使用内部锁定,将所有方法标记为同步并使用"this"将它们锁定在对象的监视器上?或者我们可以将类的"this"上标记为同步的方法替换为方法中的私有最终对象锁,以锁定通用对象锁以使其线程安全?
仅举使用内部锁定的示例代码:
public class Counter{
// Locks on the object's monitor
public synchronized void changeValue() {
// ...
}
}
我们可以用以下外在锁替换上面的代码:
public class Counter{
private final Object lock = new Object(); // private final lock object
public void changeValue() {
synchronized (lock) { // Locks on the private Object
// ...
}
}
}
是否建议使用上述外部锁而不是使用内部锁定使类作为线程安全?如果我的理解在这里有误,请纠正我?
Oracle 安全编码标准包含您需要的所有信息。
基本上是为了防止这种情况:声明为同步的方法和在此引用上同步的块都使用对象的监视器(即其内部锁)。攻击者可以通过获取并无限期持有可访问类的内部锁来操纵系统以触发争用和死锁,从而导致拒绝服务 (DoS)。
下面的示例清除了何时使用,
public class Foo {
// Locks on the object's monitor
public synchronized void changeValue() {
// ...
}
public static Foo changeState(String name) {
// Manipulate on Foo
return obj;
}
public static void main(String[] args) throws InterruptedException {
// Untrusted code
String name = "test" ;
Foo foo = Foo.changeState(name);
if (foo == null) {
throw new IllegalStateException();
}
synchronized (foo) {
while (true) {
// Indefinitely lock someObject
Thread.sleep(Integer.MAX_VALUE);
}
}
}
}
此规则用于解决要在同步块中使用的监视对象的类型。总结本文,建议使用外在锁(称为私有锁对象习语)。
- 对无法更改的对象实例具有锁定会使同步更加一致。当无法更改同步对象时,很难中断同步。
- 由于锁位于特定对象上,因此即使线程正在处理同步块,其他类资源也可用。这使得代码更健壮,更不容易受到死锁的影响。