繁体   English   中英

Java中的同步实例方法

[英]Synchronised instance methods in java

从某些互联网来源

这是一个同步实例方法:

public synchronized void add(int value){

  this.count += value;
}

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

这是我的理解。 如果我有一个可运行的对象,其中包含包含上述add方法的类的实例,则

情况1:我有两个线程,每个线程具有包含add方法的类的相同实例,那么一次只能执行一个上述add方法。 因此,如果一个线程调用add那么在完成执行之前不能抢占它吗?

情况2:如果我的两个线程都具有包含add方法的类的两个不同实例,则在这种情况下,它的同步实际上不会发挥任何作用。 他们两个将执行,好像根本没有应用同步。

我的理解正确吗?

是的,但是

那么在完成执行之前不能抢占吗?

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

好像根本没有应用同步。

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

您的理解在很大程度上是正确的。 (请参阅彼得的回答)。

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

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()的调用之前之后进行。 如果setName()在中间被抢占,则toString()将等待直到setName完成。 因此toString()要么打印“ ??” 或“ John Doe”。

Java内存模型也可能需要同步,以确保一个线程中所做的更改被另一线程看到。 但这正在变得更加先进...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM