Java并发同步问题
Java Concurrency synchronization issue
任何人都可以解释为什么下面的代码会导致竞争条件,因为我使方法同步但它的对象级锁定,我正在深入研究 java 并发。
请解释,因为如果我使用class级别肯定可以,我怀疑每个线程占用的锁都不一样。
/**
*
*/
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 之间进行上下文切换。考虑以下示例:
- 线程 #1 调用
getSharedData()
,并获得 0
- 线程 #2 调用
getSharedData()
,也得到 0
- 线程 #1 将其值加 1,并调用
setSharedData(1)
.
- 线程 #2 也将其值加 1,并调用
setSharedData(1)
,而不是您期望的 setSharedData(2)
。
解决此类问题的一种方法是不允许 class' 用户直接设置值,而是为他们提供一种自动增加值的方法:
class SharedClass {
private static int sharedData;
public synchronized int getSharedData() {
return sharedData;
}
public synchronized void incrementSharedData(int amount) {
sharedData += amount;
}
}
任何人都可以解释为什么下面的代码会导致竞争条件,因为我使方法同步但它的对象级锁定,我正在深入研究 java 并发。 请解释,因为如果我使用class级别肯定可以,我怀疑每个线程占用的锁都不一样。
/**
*
*/
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 之间进行上下文切换。考虑以下示例:
- 线程 #1 调用
getSharedData()
,并获得 0 - 线程 #2 调用
getSharedData()
,也得到 0 - 线程 #1 将其值加 1,并调用
setSharedData(1)
. - 线程 #2 也将其值加 1,并调用
setSharedData(1)
,而不是您期望的setSharedData(2)
。
解决此类问题的一种方法是不允许 class' 用户直接设置值,而是为他们提供一种自动增加值的方法:
class SharedClass {
private static int sharedData;
public synchronized int getSharedData() {
return sharedData;
}
public synchronized void incrementSharedData(int amount) {
sharedData += amount;
}
}