2011-04-19 48 views
2

直到最近,我認爲是錯誤檢查互斥鎖大多爲與正確的代碼沒有什麼價值一個調試工具,但後來我意識到它們具有可替代遞歸互斥體的屬性,如:遞歸或錯誤檢查互斥?

void foo() 
{ 
    int ok_to_unlock = !pthread_mutex_lock(m); 
    /* do something */ 
    if (ok_to_unlock) pthread_mutex_unlock(m); 
} 

注意pthread_mutex_lock如果調用者已經保持鎖定,則成功時返回0,並返回EDEADLK。這種用法的優點是您不必擔心超出任意遞歸鎖定限制; 「鎖定計數」隱含在呼叫幀中。原則上這個習語也可能會稍微好一點,因爲當調用線程已經持有鎖時,從不會調用pthread_mutex_unlock

我的問題主要是關於然後風格:不使用錯誤檢查互斥就像從代碼的清晰度此減損?是否有其他原因,你不想這樣使用它們?

+0

這聽起來很主觀。 :) – unwind 2011-04-19 13:23:45

+0

我想;但最後一句話中的問題有點非主觀的轉折點(非風格原因,這種用法會很糟糕)。 – 2011-04-19 13:26:25

+0

除了風格 - 我會研究PTHREAD_MUTEX_ERRORCHECK的性能。如果保存一些pthread_mutex_xxx調用,如果它檢測到錯誤檢查互斥是例如,它可能不值得。比普通或遞歸互斥鎖慢10倍 – nos 2011-04-19 13:27:28

回答

2

這是主觀的,但我覺得這使代碼不太清楚。

+0

同意 - 未來的維護人員可能會正確地問爲什麼「錯誤」被鎖在程序中返回,更不用說任何工具制定檢查正確性可能不惜併發程序。 – 2011-04-19 13:33:11

1

我認爲,無論性能提升你可能意識到會被首先使用錯誤檢查互斥的成本所淹沒。然而,即使這些成本可能很小,我也沒有看到任何理由不使用這個習慣用法。我唯一的意見是使用變量名稱,如locked而不是ok_to_unlock

+1

'locked'的問題是互斥鎖*被鎖定 - 這個變量指示誰有責任解鎖它(我們或者主叫者)。不管你怎麼稱呼它,如果互斥體在我們出現之前沒有被鎖定,那麼這個變量就是真的,如果它已經被鎖定了,它就是假的。 – 2011-04-19 13:29:12

+2

我可以移動'!'的'if'和名稱,如果'locked_by_caller' ... – 2011-04-19 13:36:40

2

注意pthread_mutex_lock回報0成功 和EDEADLK如果主叫方已持有鎖。

你張貼的代碼是不完全健壯,因爲EDEADLK可能被返回的唯一可能的錯誤。如果互斥體沒有正確初始化,還有EINVAL

在一個稍微切記,大衛Butenhof有一些interesting warnings關於使用遞歸互斥的。

+0

使用UB未初始化的互斥的結果,所以沒有必要考慮這種情況。 – 2011-05-09 03:44:15

+0

+1鏈接。一段有趣的歷史。我曾經同意這個觀點,直到我明白stdio鎖定和'flockfile'如何工作,這是一種遞歸互斥體。然後我意識到遞歸互斥允許您保護最小的數據操作單元,同時還允許調用者將更大的數據操作單元設置爲原子 - 在stdio的情況下,確保多個文件IO操作作爲原子單元進行。 – 2011-05-09 04:06:28