Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 要在哪些对象上进行同步?为什么局部变量不好?_Java_Multithreading_Synchronization - Fatal编程技术网

Java 要在哪些对象上进行同步?为什么局部变量不好?

Java 要在哪些对象上进行同步?为什么局部变量不好?,java,multithreading,synchronization,Java,Multithreading,Synchronization,关于堆栈溢出,有很多关于同步的资料,但我仍然没有获得关于决定将哪个对象用作内在锁的高质量内容。作为经验法则,有人真的能给出一个好的答案吗 因此,我应该选择“monitor”作为实例变量还是局部变量或拥有该方法的实例?他们三个都做得很好。此外,原语值包装类使用“池”,因此也没有问题,因为线程“攻击”相同的锁 那么为什么这样做更好呢 在此(实例变量)上: 或在此基础上(局部变量): 他们都干得很好/一样。那么,为什么我读到当局部变量隐式使用池来存储对象时,我应该避免使用它们呢?在这种情况下,变量的范

关于堆栈溢出,有很多关于同步的资料,但我仍然没有获得关于决定将哪个对象用作内在锁的高质量内容。作为经验法则,有人真的能给出一个好的答案吗

因此,我应该选择“monitor”作为实例变量还是局部变量或拥有该方法的实例?他们三个都做得很好。此外,原语值包装类使用“池”,因此也没有问题,因为线程“攻击”相同的锁

那么为什么这样做更好呢

在此(实例变量)上:

或在此基础上(局部变量):

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


谢谢

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

使用常量池对象监视器的问题如下:

String monitor = "monitor";
void methodA() {
    synchronized (monitor){
        //some code
    }
}
。。。只有一个合并的常量对象

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

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


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

它们并不是“都工作得很好/相同”。在局部变量上进行同步完全没有任何效果,因为每个调用方都有自己的值。在实例成员而不是实例上进行同步可以实现更细粒度的控制:您可以为不同的操作使用不同的监视器,而这些操作不会相互干扰。我可以问一下,您为什么在第一段中说应该是安全的吗?在给定的情况下,我们将使用该方法同步所有实例,而不仅仅是一个实例。如果我们有所有线程共享的静态变量呢?那会毁了这个计划,不是吗?这就是为什么我们需要使用“公共”实例变量作为“监视器”。我说的对吗?是的,在这种情况下,您需要一个类的所有实例都通用的锁。我已对声明进行了限定,以澄清问题。
class A {
    String monitor = "monitor";
    void methodA(){
        synchronized (monitor){
            //some code
        }
    }
}
class A {
    void methodA(){
        String monitor = "monitor";
        synchronized (monitor){
            //some code
        }
    }
}
String monitor = "monitor";
void methodA() {
    synchronized (monitor){
        //some code
    }
}