簡體   English   中英

Java多線程中的意外答案

[英]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 ,都更新restmp + 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM