在java多线程中使用“私有最终对象”锁定有什么用?

时间:2013-10-17 06:29:03

标签: java multithreading

java多线程中“私有最终对象”锁定的用途是什么?

就我的理解而言,我认为要使类成为线程安全的,我们应该使用内部锁定,我们将所有方法标记为synchronized& amp;使用“this”将它们锁定在Object的监视器上?或者我们可以用类中的私有最终Object锁替换在类的“this”上标记为synchronized的方法,以锁定通用Object锁以使其线程安全吗?

仅举例说明使用内在锁定的代码:

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
  // ...
       }
  }
}

使用外部锁定而不是使用内部锁定是否可以使类成为线程安全的?如果我的理解不对,请纠正我吗?

3 个答案:

答案 0 :(得分:7)

Oracle Secure coding standard包含您需要的所有信息。

基本上它用于防止这种情况:声明为synchronized的方法和在this引用上同步的块都使用objectâs监视器(即其内部锁)。攻击者可以通过获取并无限期地保持可访问类的内部锁来操纵系统来触发争用和死锁,从而导致拒绝服务(DoS)。

答案 1 :(得分:0)

以下示例清除了何时使用

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);
            }
        }
    }
}

答案 2 :(得分:0)

This rule 解决了要在同步块中使用的监视器对象的类型。 总结文章,推荐使用外在锁(称为私有锁对象习语)。

  1. 对无法更改的对象实例进行锁定可使同步更加一致。无法更改同步对象时,很难中断同步。
  2. 由于锁定在特定对象上,因此即使线程正在同步块上工作,其他类资源也可用。这使得代码更健壮,更不容易出现死锁。