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關系)
所以你不能有效地依賴它所做的任何事情。這只是不正確的代碼。
(此外,我知道這個問題的答案并不是因為調試多線程代碼的一些來之不易的戰斗,或者是深入的技術閱讀:我知道這一點是因為我之前在其他地方讀過這個答案。這是一個客廳技巧,僅此而已,所以詢問最小值不是一個很好的面試問題)。

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

TA貢獻1806條經驗 獲得超5個贊
在我看來,由于缺乏原子操作,達到 25 是完全不可能的。
所有線程幾乎同時啟動,因此每個線程都會看到與第一次迭代ThreadTest.num
一樣的值。0
由于有 5 個線程并行訪問同一變量,因此在第三次迭代時,線程可能會看到ThreadTest.num
值仍然為1
or?2
,并且會錯誤地增加到2
or?3
。
根據硬件的不同,最終值會更低或更高,最快的可能具有最低的值,最慢的可能具有較高的值。但我的主張是最大值不能達到 25。
編輯 (2019-10-07)
我在自己的機器(Core i5 HQ)上進行了測試,確實最終結果25
幾乎每次都達到了。為了更好地理解,我在循環中使用更大的數字進行了測試for
:
for?(int?i?=?0;?i?<?10000;?i++)?{ ????num++; }
現在,大多數時候,最終結果都在20000到30000之間,與50000相差甚遠。

TA貢獻1854條經驗 獲得超8個贊
好吧,我的答案是 Max 25,Min 0,因為你所有的操作都是遞增的,并且你將其初始化為 0.. 我認為靜態非易失性 int 被扔在那里讓你進入這些關于種族的想法條件,但是其中是否有任何東西可以在任何情況下減少數字?
編輯:就其價值而言,這將是一種典型的干擾,他們可能希望您能夠在現實世界中克服這種干擾,證明這種“欺騙”的合理性,有很多轉移注意力的事情!
添加回答
舉報