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

标签 java multithreading synchronization

这个问题在这里已经有了答案:





Clarification on the meaning of the parameter block synchronization

(3 个回答)



What does 'synchronized' mean?

(17 个回答)



How does synchronized work in Java

(4 个回答)


1年前关闭。




关于同步的堆栈溢出有很多 Material ,但我仍然没有获得关于决定将哪个对象用作内在锁的高质量内容。根据经验,有人真的可以做出一个好的答案吗?
那么我应该选择“监视器”作为实例变量还是局部变量或拥有该方法的实例?他们三个都很好地完成了这项工作。原始值包装器类也使用“池”,因此在那里也没有问题,因为线程“攻击”相同的锁。
那么为什么这样做更好(this):

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
        }
    }
}
他们都工作正常/相同。那么为什么我读到当局部变量隐式使用池来存储对象时我应该避免使用它们呢?在这种情况下,变量的范围有什么影响?
谢谢!

最佳答案

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

String monitor = "monitor";
void methodA() {
    synchronized (monitor){
        //some code
    }
}
...是有只有一个池化常量对象。
在类 A 的两个不同实例上运行的两个不同线程无法进入 methodA 中的同步块(synchronized block)同时,即使您已确保它应该是安全的(例如,您不接触静态共享状态)。
更糟糕的是:其他地方可能还有其他一些 B 类,它们也恰好在常量“监视器”字符串上同步。现在使用 B 类的线程将阻止其他不相关的线程使用 A 类。
最重要的是,创建 deadlock 非常容易。因为您在不知不觉中在线程之间共享锁。

关于java - 要同步哪些对象?为什么局部变量不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63293187/

相关文章:

Java 将特殊字符转换为 Unicode

java - 获取标题假装 netflix

python - 如何将并发查询从 Python 处理程序输入到 C 函数并将输出重定向回 Python?

java - Kotlin 中的线程同步是如何工作的?

c++ - WaitForSingleObject 问题

java - 改变锁对象

java - 扩展 JUnit assertEquals

java - 我不明白为什么这个应用程序会崩溃

linux - 如何在运行时将新消息传递给线程函数?

android - Executors.newSingleThreadScheduledExecutor().schedule 的可靠性