3 回答

TA貢獻1816條經驗 獲得超6個贊
當兩個或多個線程可以訪問共享數據并且他們嘗試同時更改它時,會發生競爭條件。因為線程調度算法可以在任何時間在線程之間交換,所以您不知道線程將嘗試訪問共享數據的順序。因此,數據變化的結果取決于線程調度算法,即兩個線程都“競相”訪問/改變數據。
當一個線程執行“check-then-act”時(例如,“檢查”,如果值為X,然后“執行”以執行取決于值為X的操作)并且另一個線程對該值執行某些操作時,通常會出現問題在“檢查”和“行為”之間。例如:
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.}
關鍵是,y可以是10,或者它可以是任何東西,這取決于另一個線程是否在檢查和行為之間改變了x。你沒有真正的認識方式。
為了防止發生競爭條件,您通常會鎖定共享數據,以確保一次只能有一個線程訪問數據。這意味著這樣的事情:
// 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貢獻1793條經驗 獲得超6個贊
當訪問共享資源的多線程(或其他并行)代碼可能以導致意外結果的方式執行時,存在“競爭條件”。
舉個例子:
for?(?int?i?=?0;?i?<?10000000;?i++?){ ???x?=?x?+?1;?}
如果您有5個線程同時執行此代碼,則x WOULD NOT的值最終為50,000,000。事實上,每次運行都會有所不同。
這是因為,為了使每個線程增加x的值,它們必須執行以下操作:(簡化,顯然)
檢索x的值將1添加到此值將此值存儲到x
任何線程都可以隨時處于此過程的任何步驟,并且當涉及共享資源時,它們可以相互踩踏。在讀取x和寫回x之間的時間內,x的狀態可以由另一個線程改變。
假設一個線程檢索x的值,但尚未存儲它。另一個線程也可以檢索相同的x值(因為還沒有線程改變它),然后它們都將相同的值(x + 1)存儲回x!
例:
線程1:讀取x,值為7線程1:將x加1,值現為8線程2:讀取x,值為7線程1:在x中存儲8線程2:將x加1,值現為8線程2:在x中存儲8
通過在訪問共享資源的代碼之前使用某種鎖定機制可以避免競爭條件:
for?(?int?i?=?0;?i?<?10000000;?i++?){ ???//lock?x ???x?=?x?+?1;? ???//unlock?x}
在這里,答案每次都是50,000,000。
添加回答
舉報