java中的同步实例方法

java中的同步实例方法,java,multithreading,synchronization,Java,Multithreading,Synchronization,从一些互联网来源 下面是一个同步实例方法: 注意在方法声明中使用了synchronized关键字。这告诉Java方法是同步的。 Java中的同步实例方法在拥有该方法的实例(对象)上同步。因此,每个实例都在不同的对象上同步其同步方法:所属实例。在同步实例方法内只能执行一个线程。如果存在多个实例,则每次可以在每个实例的同步实例方法内执行一个线程。每个实例一个线程 这是我的理解。如果我有一个可运行对象,它包含一个包含上述add方法的类的实例,那么 案例1:我有两个线程,每个线程都具有包含add方法的类

从一些互联网来源

下面是一个同步实例方法:

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

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

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

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

我的理解正确吗?

是的,但是

那么,在它完成执行之前,它不能先发制人吗

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

好像根本没有应用同步


不同之处在于,如果没有
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 ;
   }
}

由于这两种方法都是同步的,如果一个线程正在调用<代码> Set Nobe(“约翰”,“DOE”)同时调用另一个调用<代码> toStReg()/Case>,则可以将“代码”> StIDNo/<代码>在中间进行抢占,并调用toStrug(),名称仅为“Set Set”。所以

toString()
可以打印“John?”

如果两个方法都是同步的,则对
toString()
的调用将在调用
setName()
之前或之后完全发生。如果在StimeNe()中被抢占,ToStutter()将等待直到StNeNess完成。所以
toString()
将打印“?”或“John Doe”


Java内存模型可能还需要同步,以确保一个线程中所做的更改被另一个线程看到。但这已经越来越高级了……

是的,你明白了。但是请记住,对于案例1,另一个线程可以从另一个方法修改
count
。(可能是
add2
)您还可以使用
synchronized(property){}
表达式同步属性访问。Ohh ok。所以它可以被抢占,但是如果另一个线程尝试调用相同的函数add,那么这就不会发生。谢谢。我不确定如果没有同步,我会说代码“快得多”。我会说“稍微快一点”。现代JVM确实优化了同步。@user949300,对于大多数用例来说,这几乎没有什么区别,除非操作很简单,例如
+=
,在这种情况下,同步的成本要高出很多倍。当然,正确性比速度更重要。顺便说一句,使用AtomicInteger或AtomicLong更快、更具可伸缩性和线程安全性。如果两种方法都是同步的,那么它们仍然获得相同的锁,对吗?i、 同一个类的实例,将无法调用任何一个方法。正确。在本例中,Person的特定实例提供了锁。如果另一个人刚结婚,从“简”、“史密斯”变为“简”、“史密斯-琼斯”,这不会影响对John Doe实例的锁定。
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 ;
   }
}