4 回答

TA貢獻1841條經(jīng)驗 獲得超3個贊
我聲稱可能的最小值是 2。
關(guān)鍵是 的非原子性num++
,即它是一個讀和一個寫,中間可能還有其他操作。
調(diào)用線程 T1..T5:
T1讀0,T2讀0;
T1寫1,然后讀寫3次。
然后T2寫1;
那么T1讀為1;
然后T2-5完成他們所有的工作
最后,T1 寫入 2。
(注意:結(jié)果 2 不依賴于線程數(shù)或迭代次數(shù),前提是每個線程至少有 2 個。)
但誠實的答案是:這真的不重要。存在數(shù)據(jù)競爭,如JLS 17.4.5中所定義:
當(dāng)程序包含兩個未排序的沖突訪問時(第 17.4.1 節(jié) [“如果至少其中一個訪問是寫入,則對同一變量的兩次訪問(讀取或?qū)懭耄┍徽J(rèn)為是沖突的?!盷)通過事前發(fā)生的關(guān)系,據(jù)說它包含?數(shù)據(jù)競爭。
(線程中的操作之間不存在happens-before關(guān)系)
所以你不能有效地依賴它所做的任何事情。這只是不正確的代碼。
(此外,我知道這個問題的答案并不是因為調(diào)試多線程代碼的一些來之不易的戰(zhàn)斗,或者是深入的技術(shù)閱讀:我知道這一點是因為我之前在其他地方讀過這個答案。這是一個客廳技巧,僅此而已,所以詢問最小值不是一個很好的面試問題)。

TA貢獻1777條經(jīng)驗 獲得超3個贊
您的線程正在更新一個非易失性變量,這意味著它不能保證每個線程都會看到 的更新值num
。讓我們考慮以下線程的執(zhí)行流程:
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 的值刷新到內(nèi)存,線程 2,3,4,5 決定再次從內(nèi)存中2
讀取 num (出于任何原因)。num
現(xiàn)在:
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
到內(nèi)存,之后 Theard 2,3,4.. 將值刷新到內(nèi)存,顯示該數(shù)字的當(dāng)前值將3
代替5

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

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