【问题标题】:Synchronization on "this" or private Object in Java? [duplicate]Java中“this”或私有对象的同步? [复制]
【发布时间】:2012-06-25 10:09:54
【问题描述】:

可能重复:
Avoid synchronized(this) in Java?

这两段代码有什么区别?各有什么优缺点?

1)

public class Example {
    private int value = 0;

    public int getNextValue() {
        synchronized (this) {
            return value++;
        }
    }
}

2)

public class Example {
    private final Object lock = new Object();
    private int value = 0;

    public int getNextValue() {
        synchronized (lock) {
            return value++;
        }
    }
}

【问题讨论】:

  • 第二种方法几乎总是更好(AFAIK)——但为什么呢? this(只是外部的“对象”)的可见性有什么负面影响? “坏代码”怎么会干扰同步目标?
  • 您知道pubilc synchronized int getNextValue(){...}public int getNextValue(){synchronized(this){...}} 完全相同吗?

标签: java multithreading synchronization


【解决方案1】:

我选择第二种方法的主要原因是我无法控制客户端对我的类的实例做什么。

如果出于某种原因,有人决定使用我的类的实例作为锁,他们将干扰我的类中的同步逻辑:

class ClientCode {
    Example exampleInstance;

    void someMethod() {
        synchronized (exampleInstance) {
            //...
        }
    }
}

如果在我的 Example 类中,我使用了其他人无法看到的锁,它们就不会干扰我的逻辑并像上述场景那样引入任意互斥锁。

综上所述,这只是信息隐藏原理的一种应用。

【讨论】:

    【解决方案2】:

    如果我需要同时执行两个彼此独立的不同任务,我更喜欢第二个选项。

    例如:

    public class Example {
        private int value = 0;
        private int new_value = 0;
        private final Object lock1 = new Object();
        private final Object lock2 = new Object();
    
        public int getNextValue() {
            synchronized (lock1) {
                return value++;
            }
        }
    
        public int getNextNewValue() {
            synchronized (lock2) {              
                return new_value++;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我会说第二种方法更好。考虑以下情况:

      public class Abc{
      
          private int someVariable;
      
          public class Xyz {
              //some method,synchronize on this
          }
      
              //some method, and again synchronize on this
      
      
      }
      

      在这种情况下this在这两种方法中是不一样的。一种是内部类的方法。因此,最好使用公共对象进行同步。例如,synchronized (someVariable)

      【讨论】:

      • 不过你可以使用synchronize(Abc.this)
      • 是的。这也是另一种选择,但问题是关于this,即当前Object 的参考。我可能是错的,但仍然是初学者。 :-)
      • Java Concurrency in Practice 一书中有这个错误。
      【解决方案4】:

      我认为这真的取决于情况。假设您的类是一个子类,而超类有一个具有同步的方法。假设您正在使用相同的数据集,并希望在您的方法中保持完整性。那么绝对方法1是你应该使用的。

      根据 Costi 提到的内容,否则第二种方法会更好

      【讨论】:

      • 我同意你的观点,但在这种情况下,我会说超类的设计不太正确;它可以提供一个protected 锁,我可以在子类中使用它,而无需公开整个同步逻辑。
      • @CostiCiudatu 完全同意你的看法。这仅适用于您从其他人的代码库继承某些类的情况。这可能很少见。
      • +1 表示高质量的讽刺——This is probably rare :)。我的意思是要强调,当您可以选择时,建议使用这种方法,而只是在某些情况下唯一可用的方法。
      猜你喜欢
      • 2012-08-12
      • 2012-02-03
      • 1970-01-01
      • 2016-05-08
      • 2014-02-07
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多