【问题标题】:Java Object Assignment and LockingJava 对象分配和锁定
【发布时间】:2012-08-16 16:46:56
【问题描述】:

考虑如下代码sn-p:

 Object bar1  = new ... ; 
 Object bar2 = new ... ; 


 Object foo = (either bar1 or bar2) ; 

现在,foo 在程序的不同时间可以是 bar1 或 bar2。我只是想检查 synchronized(foo) 是否会锁定相应的 bar1 或 bar2。鉴于对象没有在 Java 中复制,这似乎是最有可能的情况。这是正确的吗?

【问题讨论】:

    标签: java synchronization locking


    【解决方案1】:
    Object bar1 = new Object();
    Object foo = bar1;
    synchronized(foo) {
        ...
    }
    

    将锁定foo==bar1

    但是,这是一个奇怪且容易出错的结构。例如:

    • 线程 1 到达您的方法和 foo == bar1
    • 线程 1 到达同步块并锁定 bar1
    • 线程 2 到达您的方法和 foo == bar2
    • 线程 2 到达同步块并锁定 bar2

    现在您有 2 个线程同时运行同步块。我真的找不到你想要那个的理由。如果你这样做了,那么块可能不应该被同步,你应该使用不同的锁定策略。

    另见this related post

    【讨论】:

    • +1 一般来说,同步除final 字段之外的任何内容都是一个坏主意。如果bar1bar2 需要同步,则应在内部同步。
    【解决方案2】:

    是的。您不是在参考上同步,而是在基础对象上同步。

    每个对象都有一个关联的监视器,当您使用synchronized 时,您将锁定它。来自here

    在Java虚拟机中,每个对象和类都是逻辑上的 与监视器相关联。对于对象,关联的监视器 保护对象的实例变量。对于课程,监视器 保护类的类变量

    【讨论】:

      【解决方案3】:

      是的,它将锁定foo 指向的任何对象。但是,我强烈建议您将 foo 设为 final 以避免这样的情况:

      Object foo = bar1;
      synchronized(foo) {
         foo = bar2;
      }
      

      因为它会导致多个线程看到不同的锁。另请参阅此问题:Locking on a mutable object - Why is it considered a bad practice?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 2010-09-07
        • 1970-01-01
        相关资源
        最近更新 更多