要同步哪些对象?为什么局部变量不好?

What objects to synchronize on? Why are local variables bad?

关于同步的堆栈溢出有很多material,但我仍然没有获得关于决定将哪个对象用作内部锁的优质内容。根据经验,有人真的可以给出一个好的答案吗?

那么我应该选择'monitor'作为实例变量还是局部变量或拥有该方法的实例?他们三个都做得很好。同样原始值包装器 类 使用 'pools' 所以也没有问题,因为线程 'attack' 相同的锁。

那么为什么这样做更好:

class A {
    void methodA(){
        synchronized (this){
            //some code    
        }
    }
}

关于这个(实例变量):

class A {
    String monitor = "monitor";
    void methodA(){
        synchronized (monitor){
            //some code
        }
    }
}

或超过这个(局部变量):

class A {
    void methodA(){
        String monitor = "monitor";
        synchronized (monitor){
            //some code
        }
    }
}

它们都有效 fine/same。那么,为什么我读到当局部变量隐式使用池来存储对象时我应该避免局部变量呢?在这种情况下变量的范围有什么关系?

谢谢!

您应该避免使用存储在局部变量中的对象的监视器,因为通常只有当前线程可以访问存储在局部变量中的对象。但由于在这种特殊情况下,局部变量实际上持有来自常量池的全局共享对象,因此您不会遇到该特定问题。

像这里这样使用常量池对象监视器的问题:

String monitor = "monitor";
void methodA() {
    synchronized (monitor){
        //some code
    }
}

...是只有一个池常量对象。

在 class A 的两个不同实例上运行的两个不同线程不能同时进入 methodA 中的同步块,即使您已确保它应该是安全的(例如,你不接触静态共享状态)。

更糟糕的是:其他地方可能还有其他 class B,它也恰好在常量“monitor”字符串上同步。现在使用 class B 的线程将阻止其他不相关的线程使用 class A.

最重要的是,创建 deadlock 非常容易,因为您会在不知不觉中在线程之间共享锁。