亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

競爭條件:整數的最小和最大范圍

競爭條件:整數的最小和最大范圍

阿波羅的戰車 2023-09-13 10:57:39
我最近在一次采訪中被問到這個問題。給定以下代碼,靜態整數的最小和最大可能值是多少num?import java.util.ArrayList;import java.util.List;public class ThreadTest {    private static int num = 0;    public static void foo() {        for (int i = 0; i < 5; i++) {            num++;        }    }    public static void main(String[] args) throws Exception{        List<Thread> threads = new ArrayList<Thread>();        for (int i = 0; i < 5; i++) {            Thread thread = new Thread(new Task());            threads.add(thread);            thread.start();        }        for (int i = 0; i < 5; i++) {            threads.get(i).join();        }        // What will be the range of num ???        System.out.println(ThreadTest.num);    }}class Task implements Runnable {    @Override    public void run() {        ThreadTest.foo();    }}我告訴他們最大值為 25(如果沒有競爭條件),最小值為 5(如果每次迭代時所有線程之間都存在競爭條件)。但面試官說最小值甚至可以低于5。這怎么可能?
查看完整描述

4 回答

?
偶然的你

TA貢獻1841條經驗 獲得超3個贊

我聲稱可能的最小值是 2。

關鍵是 的非原子性num++,即它是一個讀和一個寫,中間可能還有其他操作。

調用線程 T1..T5:

  • T1讀0,T2讀0;

  • T1寫1,然后讀寫3次。

  • 然后T2寫1;

  • 那么T1讀為1;

  • 然后T2-5完成他們所有的工作

  • 最后,T1 寫入 2。

(注意:結果 2 不依賴于線程數或迭代次數,前提是每個線程至少有 2 個。)

但誠實的答案是:這真的不重要。存在數據競爭,如JLS 17.4.5中所定義:

當程序包含兩個未排序的沖突訪問時(第 17.4.1 節 [“如果至少其中一個訪問是寫入,則對同一變量的兩次訪問(讀取或寫入)被認為是沖突的?!盷)通過事前發生的關系,據說它包含?數據競爭。

(線程中的操作之間不存在happens-before關系)

所以你不能有效地依賴它所做的任何事情。這只是不正確的代碼。

(此外,我知道這個問題的答案并不是因為調試多線程代碼的一些來之不易的戰斗,或者是深入的技術閱讀:我知道這一點是因為我之前在其他地方讀過這個答案。這是一個客廳技巧,僅此而已,所以詢問最小值不是一個很好的面試問題)。


查看完整回答
反對 回復 2023-09-13
?
慕森王

TA貢獻1777條經驗 獲得超3個贊

您的線程正在更新一個非易失性變量,這意味著它不能保證每個線程都會看到 的更新值num。讓我們考慮以下線程的執行流程:

Thread 1: 0->1->2 (2 iteration left)
Thread 2: 0->1->2->3 (1 iteration left)
Thread 3: 0->1->2->3 (1 iteration left)
Thread 4: 0->1->2->3 (1 iteration left)
Thread 5: 0->1->2->3 (1 iteration left)

此時,線程 1 將 num 的值刷新到內存,線程 2,3,4,5 決定再次從內存中2讀取 num (出于任何原因)。num現在:

Thread 1: 2->3->4 (completed 2 iteration)
Thread 2: 2->3 (completed 1 iteration)
Thread 3: 2->3 (completed 1 iteration)
Thread 4: 2->3 (completed 1 iteration)
Thread 5: 2->3 (completed 1 iteration)

線程 1 將值刷新4到內存,之后 Theard 2,3,4.. 將值刷新到內存,顯示該數字的當前值將3代替5


查看完整回答
反對 回復 2023-09-13
?
忽然笑

TA貢獻1806條經驗 獲得超5個贊

在我看來,由于缺乏原子操作,達到 25 是完全不可能的。

所有線程幾乎同時啟動,因此每個線程都會看到與第一次迭代ThreadTest.num一樣的值。0由于有 5 個線程并行訪問同一變量,因此在第三次迭代時,線程可能會看到ThreadTest.num值仍然為1or?2,并且會錯誤地增加到2or?3。

根據硬件的不同,最終值會更低或更高,最快的可能具有最低的值,最慢的可能具有較高的值。但我的主張是最大值不能達到 25。

編輯 (2019-10-07)

我在自己的機器(Core i5 HQ)上進行了測試,確實最終結果25幾乎每次都達到了。為了更好地理解,我在循環中使用更大的數字進行了測試for

for?(int?i?=?0;?i?<?10000;?i++)?{
????num++;
}

現在,大多數時候,最終結果都在20000到30000之間,與50000相差甚遠。


查看完整回答
反對 回復 2023-09-13
?
嗶嗶one

TA貢獻1854條經驗 獲得超8個贊

好吧,我的答案是 Max 25,Min 0,因為你所有的操作都是遞增的,并且你將其初始化為 0.. 我認為靜態非易失性 int 被扔在那里讓你進入這些關于種族的想法條件,但是其中是否有任何東西可以在任何情況下減少數字?

編輯:就其價值而言,這將是一種典型的干擾,他們可能希望您能夠在現實世界中克服這種干擾,證明這種“欺騙”的合理性,有很多轉移注意力的事情!


查看完整回答
反對 回復 2023-09-13
  • 4 回答
  • 0 關注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號