2012-05-21 44 views
3

如果我有一個關鍵部分,我必須實現一個鎖定它的方法。我看到了以下的變體:輪詢鎖是否實現關鍵部分的正確方法?

while(lock) 
{ 
    //do nothing 
} 
lock = true; 
// code of critical section 
lock = false; 

然而,我懷疑它,因爲在理論上,幾個線程可以執行while(lock)(檢查,看看它的= FALSE),並進入臨界區一起,因爲while(lock)lock = true;不是在一個連續的塊中執行的。我錯了嗎?或者這確實是一種不安全的方法?

+0

你需要一個鎖,所以使用一個鎖。 –

回答

3

這是「幾乎安全」,即根本不安全。它缺少的正是你所看到的 - 多個線程可能會看到lock == false並進入關鍵部分。它需要一個原子操作,它必須被硬件支持 - 一種保證只有一個執行線程可以獲得鎖的方法。這就是說,如果你正在編寫的系統可以在互斥排除失敗的情況下繼續存在,並且可以在偶爾的失敗情況下工作(可能是日誌記錄或者偶然的錯位輸入不一定會導致完全失敗的東西),那麼這種模式可以「排序」工作...

+0

「它需要一個原子操作,它必須被硬件支持」 - 這應該是彙編代碼中的指令,或者有準備好的機制? –

+1

它是CPU指令集中的一條指令(或幾條中的一條)。如果你的編譯器支持這樣的結構,它可以通過原始彙編代碼或內聯彙編代碼進行訪問。更好的辦法是利用已經有正確的例程編寫的線程/併發庫,但你沒有提到這是Linux與gcc或Windows與VC + +或其他... – twalberg

+0

好吧,謝謝你,將深入瞭解。我正在使用Embarcadero RAD Studio C++ Builder 2010. –

5

你是對的 - 這是不安全的。沒什麼比這更多的說。

編輯:不,真的,真的沒有太多可以說這個構造。這是而不是自旋鎖,也不像自旋鎖。對於一個自旋鎖,你需要的東西含糊這樣的:

// note: incomplete, not reentrant, not intended for real use 
atomic_type spin_lock = 0; 

// enter the spin lock: 
int prev_value; 

while ((prev_value = test_and_set(&spin_lock, 1)) != 0 || spin_lock != 1) 
    ; 
// code of critical section 

// release the spin lock: 
test_and_set(&spin_lock, 0); 

這裏最重要的一點是,進入自旋鎖,你需要獲得前值和設定新的價值原子。然後你必須確認你的寫入鎖從「非擁有」改爲「擁有」狀態。

+0

您也是正確的,但僅適用於第一句。還有很多話要說。 –

+0

@JensGustedt:關於線程安全編程(以及其他)肯定還有很多話要說,但關於這個特定的構造還不多說。 –

0

你試圖實現的稱爲自旋鎖。新的C標準C11實現了一個名爲atomic_flag的原始數據類型,可以像那樣使用它。幾乎所有的現代硬件都支持它,但不幸的是,大多數編譯器還不是完全支持語法級別的編譯器,而是擁有自己的擴展。例如,gcc已經爲此建立了__sync_lock_test_and_set__sync_lock_release

+0

這不是自旋鎖,甚至不像自旋鎖。 –