我想了解C中的多線程編程。爲什麼要使用互斥鎖而不是布爾變量來進行線程同步?
我懷疑當我們使用MUTEXES進行線程同步時,爲什麼我們不能使用布爾變量來阻塞要執行的代碼的關鍵區域。
靜音布爾變量的特性是什麼? PS:其實這個問題在面試中被問到。 所以請分享你的知識。
我想了解C中的多線程編程。爲什麼要使用互斥鎖而不是布爾變量來進行線程同步?
我懷疑當我們使用MUTEXES進行線程同步時,爲什麼我們不能使用布爾變量來阻塞要執行的代碼的關鍵區域。
靜音布爾變量的特性是什麼? PS:其實這個問題在面試中被問到。 所以請分享你的知識。
首先,您的建議並不完全清楚。假設你有五個線程全部競爭同一資源。很明顯你將如何使用互斥體來確保獨佔訪問。目前還不清楚如何爲此使用布爾變量。
也就是說,布爾變量有時可用於同步。但是,適用的情況是有限的,並且有一些注意事項(例如,這種變量通常需要聲明爲volatile
)。
互斥鎖適用範圍更廣。值得一提的是,除了(正確)確保只有一個線程可以進入受保護區段外,它們還可以作爲memory barriers。
如果您嘗試使用布爾值作爲「假互斥量」,我可以很容易地指出您實現中的缺陷,直到您基本結束重新創建互斥鎖爲止。互斥體基本上是一個布爾類型,所有額外的東西都需要用於線程同步。
int locked = 0;
void lock(void) {
while (locked) sleep_api(little);
locked = 1;
return;
}
這段代碼是錯誤的,因爲兩個線程可以同時在鎖定變量中看到0,並認爲他們有鎖。
問題是兩個線程都可以同時看到布爾值可用,並且兩者都會假定它可以繼續安全。
例如,假設你有這樣的代碼:
bool myLock = false; // visible to all threads
void someFunction()
{
if (!myLock)
{
myLock = true;
// do whatever
// and then release the lock
mylock = false;
}
}
現在,想象一下兩個線程執行。線程A讀取myLock
並看到它是false
,所以它繼續下一條指令。與此同時,線程B讀取myLock
並且看到它是false
,因爲線程A尚未將其設置爲true
。因此,線程B向前邁進並且也取得了鎖定。此時,兩個線程正在執行應該受互斥鎖保護的代碼。
它變得更糟,因爲線程A完成它正在做的事情,並且在線程B仍在執行時將mylock
設置回false
。所以即使線程B仍然在那裏,另一個線程可以繼續並鎖定。
一個互斥體保證了原子性。也就是說,它保證了檢查和更新一次只能由一個線程完成。所以,如果你有一個互斥體代替布爾,您有:
if (mutex.Acquire())
{
// do stuff
// then release the lock
mutex.Release();
}
有沒有機會,兩個線程可以同時獲取互斥。
」檢查和更新一次只能由一個線程完成。「回到本質上,這是否意味着可以完成檢查,並且有一個上下文切換,但其他線程知道有一個檢查和更新的地方,所以他們不會嘗試?換句話說,我問的是,互斥體是如何工作的,它只是自然的原子或者知道只有線程可以執行檢查和更新並且可以進行檢查 - 另一個線程進入並更新,而在另一個線程中它知道檢查更新正在進行,所以不能這樣做? – Celeritas
互斥體是天然原子。它使用執行原子檢查和更新的CPU指令。所以如果一個線程開始獲取互斥體,那麼另一個線程就不可能這麼做。 –
不錯的例子。如果只有一個線程會寫入布爾值,另一個線程將成爲從布爾值讀取的唯一線程?那麼它會安全嗎? –
這取決於。布爾值是什麼意思,線程在做什麼,取決於布爾值? 「 – manuell