我正在尝试理解Java中的同步。 我明白,如果我从 2 个不同的线程访问同一个对象上的同步方法,则一次只有一个能够访问。
但我认为如果在两个不同的实例上调用相同的方法,两个对象应该能够并行访问该方法。如果从方法访问/修改静态成员变量,这会导致竞争条件。但我无法看到下面代码中发生的竞争条件。
有人可以解释一下代码或我的理解有什么问题吗?
引用代码可访问:http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
最佳答案
你是对的,竞争条件存在。但活泼的操作是如此之快,以至于它们不太可能发生 - 并且 synchronized
关键字可能提供同步“帮助”,虽然 JLS 不需要,但隐藏了竞争。
如果你想让它更明显一点,你可以“拼出”count = count + 1
代码并进入休眠状态:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
这应该更容易地显示比赛。 (顺便说一句,我对中断异常的处理不太适合生产代码;但对于像这样的小型测试应用程序来说已经足够了。)
这里学到的教训是:通过测试很难捕捉竞争条件,因此最好真正理解代码并向自己证明它是正确的。
关于java - 多个线程从不同实例访问实例方法会导致竞争条件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24415118/