[英]unexpected answers in multithreading in java
這是我的代碼,使用4個線程將變量'res'相加4 * 10 ^ 7一次:
class MathSin extends Thread {
public double a;
public MathSin(int degree) {
a = degree;
}
@Override
public void run() {
for (int i = 0; i < Math.pow(10., 7); i++)
MathThreads.res++;
}
}
class MathThreads {
public static double res = 0;
public static void main(String args[]) {
MathSin st = new MathSin(8);
MathSin ct = new MathSin(8);
MathSin tt = new MathSin(8);
MathSin qt = new MathSin(8);
st.start();
ct.start();
tt.start();
qt.start();
try { // wait for completion of all thread and then sum
st.join();
ct.join(); // wait for completion of MathCos object
tt.join();
qt.join();
System.out.println(res);
} catch (InterruptedException IntExp) {
}
}
}
這些是一些答案:
1.8499044E7
2.3446789E7
.
.
.
我期望得到3.0E7,但會得到另一個不同的答案。
如何解決這個問題?
在更新static
變量res
時,您正在觀察競爭條件。
MathThreads.res++
等效於:
double tmp = MathThreads.res;
MathThreads.res = tmp + 1;
現在發生了什么事,如果兩個線程在同一時間讀取值tmp
,都更新res
與tmp + 1
? 好吧,只是簡單地忘記了一個增量: res
最終是tmp + 1
而不是tmp + 1 + 1
!
因此,通過4個線程並發更新res
,您最終只會得到未定義的行為:由於這些競爭條件,無法預測res
的最終值。 相同代碼的兩次執行將為您提供不同的答案。
為了使代碼具有線程安全性,您需要對res
使用線程安全結構:可以同時更新和訪問的結構。
在您的情況下, AtomicLong
似乎是最佳選擇:
public static AtomicLong res = new AtomicLong(0);
並在運行方法中:
for (int i = 0; i < Math.pow(10., 7); i++) {
MathThreads.res.incrementAndGet();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.