任何人都可以解释为什么下面的代码会导致竞争条件,因为我使方法同步但对象级别锁定,我正在深入了解java并发。请解释一下,因为如果我使用类级别肯定会工作,我怀疑线程占用的锁是不同的。
/**
*
*/
package lession2.shared.object;
/**
* @author so_what
*
*/
class SharedClass {
private static int sharedData;
public synchronized int getSharedData() {
return sharedData;
}
public synchronized void setSharedData(int sharedData) {
SharedClass.sharedData = sharedData;
}
}
//output of the program should be the distinct numbers
public class StaleDataExample extends Thread {
static SharedClass s1=new SharedClass();
static int counter=0;
public static void main(String args[]) throws InterruptedException {
StaleDataExample t1=new StaleDataExample();
StaleDataExample t2=new StaleDataExample();
StaleDataExample t3=new StaleDataExample();
StaleDataExample t4=new StaleDataExample();
StaleDataExample t5=new StaleDataExample();
StaleDataExample t6=new StaleDataExample();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
System.out.println();
}
public void run()
{
s1.setSharedData(s1.getSharedData()+1); //read->modify->write operation
System.out.print(s1.getSharedData()+" ");
}
}
这里的问题是您没有以原子(例如同步)的方式递增共享值。
我们来看看以下几行:
s1.setSharedData(s1.getSharedData()+1)
首先,调用getSharedData
,它是synchronized. You then increment the value, at call
setSharedData`来设置新值。问题是程序可以在get和set之间进行上下文切换。请考虑以下示例:
getSharedData()
,得到0getSharedData()
,也获得0setSharedData(1)
。setSharedData(1)
,而不是您期望的setSharedData(2)
。解决此类问题的一种方法是不允许类'用户直接设置值,而是为它们提供一个原子递增值的方法:
class SharedClass {
private static int sharedData;
public synchronized int getSharedData() {
return sharedData;
}
public synchronized void incrementSharedData(int amount) {
sharedData += amount;
}
}