3 回答

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個(gè)贊
當(dāng)兩個(gè)或多個(gè)線程可以訪問共享數(shù)據(jù)并且他們嘗試同時(shí)更改它時(shí),會發(fā)生競爭條件。因?yàn)榫€程調(diào)度算法可以在任何時(shí)間在線程之間交換,所以您不知道線程將嘗試訪問共享數(shù)據(jù)的順序。因此,數(shù)據(jù)變化的結(jié)果取決于線程調(diào)度算法,即兩個(gè)線程都“競相”訪問/改變數(shù)據(jù)。
當(dāng)一個(gè)線程執(zhí)行“check-then-act”時(shí)(例如,“檢查”,如果值為X,然后“執(zhí)行”以執(zhí)行取決于值為X的操作)并且另一個(gè)線程對該值執(zhí)行某些操作時(shí),通常會出現(xiàn)問題在“檢查”和“行為”之間。例如:
if (x == 5) // The "Check"{ y = x * 2; // The "Act" // If another thread changed x in between "if (x == 5)" and "y = x * 2" above, // y will not be equal to 10.}
關(guān)鍵是,y可以是10,或者它可以是任何東西,這取決于另一個(gè)線程是否在檢查和行為之間改變了x。你沒有真正的認(rèn)識方式。
為了防止發(fā)生競爭條件,您通常會鎖定共享數(shù)據(jù),以確保一次只能有一個(gè)線程訪問數(shù)據(jù)。這意味著這樣的事情:
// Obtain lock for xif (x == 5){ y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10}// release lock for x

TA貢獻(xiàn)1793條經(jīng)驗(yàn) 獲得超6個(gè)贊
當(dāng)訪問共享資源的多線程(或其他并行)代碼可能以導(dǎo)致意外結(jié)果的方式執(zhí)行時(shí),存在“競爭條件”。
舉個(gè)例子:
for?(?int?i?=?0;?i?<?10000000;?i++?){ ???x?=?x?+?1;?}
如果您有5個(gè)線程同時(shí)執(zhí)行此代碼,則x WOULD NOT的值最終為50,000,000。事實(shí)上,每次運(yùn)行都會有所不同。
這是因?yàn)?,為了使每個(gè)線程增加x的值,它們必須執(zhí)行以下操作:(簡化,顯然)
檢索x的值將1添加到此值將此值存儲到x
任何線程都可以隨時(shí)處于此過程的任何步驟,并且當(dāng)涉及共享資源時(shí),它們可以相互踩踏。在讀取x和寫回x之間的時(shí)間內(nèi),x的狀態(tài)可以由另一個(gè)線程改變。
假設(shè)一個(gè)線程檢索x的值,但尚未存儲它。另一個(gè)線程也可以檢索相同的x值(因?yàn)檫€沒有線程改變它),然后它們都將相同的值(x + 1)存儲回x!
例:
線程1:讀取x,值為7線程1:將x加1,值現(xiàn)為8線程2:讀取x,值為7線程1:在x中存儲8線程2:將x加1,值現(xiàn)為8線程2:在x中存儲8
通過在訪問共享資源的代碼之前使用某種鎖定機(jī)制可以避免競爭條件:
for?(?int?i?=?0;?i?<?10000000;?i++?){ ???//lock?x ???x?=?x?+?1;? ???//unlock?x}
在這里,答案每次都是50,000,000。
添加回答
舉報(bào)