来自某些互联网资源
这是一个同步的实例方法:
public synchronized void add(int value){
this.count += value;
}
请注意在方法声明中使用synchronized关键字。这告诉Java该方法是同步的。 Java中的同步实例方法在拥有该方法的实例(对象)上同步。因此,每个实例的同步方法在不同的对象上同步:拥有实例。只有一个线程可以在同步实例方法中执行。如果存在多个实例,则一次一个线程可以在每个实例的同步实例方法内执行。每个实例一个线程。
这是我的理解。如果我有一个runnable对象,它包含一个包含上述add方法的类的实例,那么
案例1:我有两个线程,每个线程都有包含add方法的 相同的 类实例,然后只有一个线程可以执行上面的add方法一时间因此,如果一个线程调用add
,那么它在完成执行之前不能被抢占?
案例2:如果我的两个线程都有两个包含add方法的 不同的 实例,那么在这种情况下它的同步并不会起任何作用。它们中的两个将执行,就好像根本没有应用同步一样。
我的理解是否正确?
答案 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内存模型也可能需要同步,以确保另一个线程可以看到在一个线程中进行的更改。但那是越来越先进......