java中的同步实例方法

时间:2014-10-07 21:07:15

标签: java multithreading synchronization

来自某些互联网资源

  

这是一个同步的实例方法:

public synchronized void add(int value){

  this.count += value;
}
  

请注意在方法声明中使用synchronized关键字。这告诉Java该方法是同步的。   Java中的同步实例方法在拥有该方法的实例(对象)上同步。因此,每个实例的同步方法在不同的对象上同步:拥有实例。只有一个线程可以在同步实例方法中执行。如果存在多个实例,则一次一个线程可以在每个实例的同步实例方法内执行。每个实例一个线程。

这是我的理解。如果我有一个runnable对象,它包含一个包含上述add方法的类的实例,那么

案例1:我有两个线程,每个线程都有包含add方法的 相同的 类实例,然后只有一个线程可以执行上面的add方法一时间因此,如果一个线程调用add,那么它在完成执行之前不能被抢占?

案例2:如果我的两个线程都有两个包含add方法的 不同的 实例,那么在这种情况下它的同步并不会起任何作用。它们中的两个将执行,就好像根本没有应用同步一样。

我的理解是否正确?

2 个答案:

答案 0 :(得分:1)

是的,但是

  

然后在完成执行之前不能预先占用它?

锁定不会阻止线程被抢占,但它会阻止任何其他线程获得相同的锁定。即使线程在锁定时可以短时间停止,它看起来也是一样的。

  

好像根本没有应用同步。

不同之处在于没有synchronized它会更快。因为这是一个如此简单的操作。如果你做的事情不那么重要,那么同步的成本会相对较小。无论如何,在几乎所有情况下,正确性都比速度更重要。

答案 1 :(得分:0)

您的理解基本上是正确的。 (见彼得的回答)。

这是一个(愚蠢的)例子。

public class Person {
   private String firstName = "?";  // set an initial value
   private String lastName = "?";

   public void setName(String first, String last) {
      this.firstName = first;
      this.lastName = last;
   }

   public String toString() {
      return firstName + " " + lastName ;
   }
}

由于两个方法都没有同步,如果一个线程正在调用setName("John", "Doe"),而另一个线程正在调用toString(),那么setName可能在中间被抢占,并且要调用toString(),名称仅为" half-set"。所以toString()可以打印" John?"。

如果两种方法都是同步的,则toString()的调用将在之前完全发生,或完全在之后,调用setName()& #39 ;.如果setName()在中间被抢占,toString()将等到setName完成。所以toString()会打印"? ?"或" John Doe"。

Java内存模型也可能需要同步,以确保另一个线程可以看到在一个线程中进行的更改。但那是越来越先进......