[英]Sharing variable between threads in JAVA
我有兩個線程對一個公共變量“ n”進行計算,一個線程每次增加“ n”,另一個線程每次減少“ n”,當我不在此變量上使用volatile關鍵字時,我無法理解的事情發生了,請幫忙解釋一下,代碼段如下:
public class TwoThreads {
private static int n = 0;
private static int called = 0;
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
n = 0;
called = 0;
TwoThreads two = new TwoThreads();
Inc inc = two.new Inc();
Dec dec = two.new Dec();
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
while (called != 2) {
//System.out.println("----");
}
System.out.println(n);
}
}
private synchronized void inc() {
n++;
called++;
}
private synchronized void dec() {
n--;
called++;
}
class Inc implements Runnable {
@Override
public void run() {
inc();
}
}
class Dec implements Runnable {
@Override
public void run() {
dec();
}
}
}
1)我期望執行后為“ n = 0,稱為= 2”,但是主線程可能會在while循環中被阻塞;
2)但是當我取消注釋該行時,程序按預期進行:
//System.out.println("----");
3)我知道我應該在“被叫”上使用“易失性”,但是我無法解釋為什么會發生上述情況;
4)“被調用”是特定線程工作存儲器中的“讀取和加載”,但是為什么在“ long” while循環之后不將其“存儲並寫入”主線程,如果不是,為什么簡單的“打印”行可以有所作為
您已同步寫入數據(以inc和dec為單位),但尚未讀取數據(以main為主)。 兩者都應同步以獲得可預期的效果。 否則,main可能永遠不會“看到” inc和dec所做的更改。
您不知道確切執行被調用的++的位置,您的主線程將繼續產生新的線程,這將導致相互排斥,我的意思是每次只能有一個線程可以執行被調用的++,因為方法是同步的,並且您不知道每個線程確切的線程將是它。 在主線程達到您的條件時,可能執行兩次n ++或n--,您可能不知道,可能執行十次n ++。
並嘗試閱讀有關數據競賽的信息
while (called != 2) {
//System.out.println("----");
}
//.. place for data race, n can be changed
System.out.println(n);
你需要同步訪問called
這里:
while (called != 2) {
//System.out.println("----");
}
我建議添加getCalled
方法
private synchronized int getCalled() {
return called;
}
並用getCalled() != 2
替換called != 2
getCalled() != 2
如果您對為什么會發生此問題感興趣,可以閱讀有關Java內存模型上下文中的可見性的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.