在Java中,synchronized块可以在任何对象引用上同步吗?

时间:2012-08-09 03:02:25

标签: java

我想知道是否存在这种陈述是真实和需要的情况。我见过的所有例子都只是在“this”引用上同步。有人能告诉我一个对象中的代码块如何在除此之外的任何其他引用上同步?

4 个答案:

答案 0 :(得分:1)

是的,陈述是真的。

为什么人们不希望使用内在监视器(synchronized(this))有几个原因 - 其中一个原因是它可以创建活动问题 - 在下面的代码中,B使用A的实例作为锁定,可能是为了控制对该变量的访问。如果另一个线程使用相同的A实例并尝试运行a.methodA(),则在methodB()结束之前它将被阻止。

因此,使用内部监视器会暴露同步策略,并可能导致细微的错误和性能问题。

public class A {

    public synchronized void methodA() {}

}

public class B {
    A a = new A();
    public void methodB() {
        synchronized(a) {
            // do something a little long
        }
    }
    public A getA() {return a;}
}

如果A使用内部监视器,则无法解决问题。

public class A {
    private final Object lock = new Object();

    public void methodA() {
        synchronized(lock) {}
    }

}

使用ad hoc监视器的另一种情况是,当一个类包含2个(或更多)不相关的对象时,需要以同步的方式访问它们。使用2个监视器而不是1个监视器可以减少争用,因为现在可以同时访问2个对象。

答案 1 :(得分:0)

在Java中,您可以使用synchronized构造在任何对象引用上创建内部锁,是的。阅读相关的Java Tutorial

使用synchronized的直接示例是在Class对象上进行同步,即how static synchronized methods work。实际上,有很多有效的用途。您可能希望避免使用synchronized (this)来支持内部实现锁定,否则您将设置一个内部使用锁定的限制,而您不知道的其他代码可能会违反。

但是,您应该知道,通常可以将synchronized用法替换为ReentrantLock。您可以在my post here中了解详情。

答案 2 :(得分:0)

是的,可以做到。

同步块将使用该对象作为锁,而不是整个类。使用synchronized(this){}的人在整个对象上放置一个独占锁,这可能就是你想要的。但是,您可能有类似persister的东西,这是唯一需要同步的东西。 synchronized(persister){},提供了一种不太精细的方法。

答案 3 :(得分:0)

public class SyncTest{
    private Object obj = new Object();

    public void func1() {
        synchronized(obj) {
            obj.something();
        }
}