2010-03-09 111 views
13

我在Linux上使用讀寫鎖,我發現試圖將讀鎖定對象升級到寫鎖死鎖。pthreads:讀寫器鎖,將讀鎖升級到寫鎖

// acquire the read lock in thread 1. 
pthread_rwlock_rdlock(&lock); 

// make a decision to upgrade the lock in threads 1. 
pthread_rwlock_wrlock(&lock); // this deadlocks as already hold read lock. 

我讀過的手冊頁,它是非常具體的。

調用線程可能死鎖如果在 呼叫作出時其持有的 讀寫鎖(無論是讀或寫 鎖)。

在這些情況下將讀鎖升級到寫鎖的最佳方式是什麼?我不想在我保護的變量上引入競爭。

大概我可以創建另一個互斥體來包含釋放讀鎖和獲取寫鎖但我真的看不到使用讀/寫鎖。我不妨簡單地使用一個普通的互斥鎖。

THX

+0

Boost.Thread具有UpgradeLockable概念,但如果您的代碼在pthread中已經非常深入,我懷疑這對您有多大用處。 – 2010-03-09 09:55:14

+0

@Steve。你知道它是如何實施的嗎?它是否使用我正在考慮的獨立互斥體? 我想我可以下載它並檢查出來:o) – ScaryAardvark 2010-03-09 18:03:25

+0

不,我不知道Boost.Thread是如何做到的,對不起。 – 2010-03-09 21:50:47

回答

15

在以下情況下,還需要死鎖嗎?

  • 線程1獲取讀鎖
  • 線程2獲取讀鎖
  • 線程1要求升級鎖定寫
  • 線程2要求升級鎖定寫

所以我d只是釋放讀鎖,獲取寫鎖並再次檢查是否需要更新。

+0

如果另一個線程持有讀鎖,爲什麼會有一個線程獲得寫鎖定?如果兩者最終都可以獲得寫入鎖定,那麼第二個問題就是所有已經創建的檢查都必須重做,因爲受保護的資源可能已經發生了重大變化。因此釋放和重新獲取提供了相同的行爲。 – AProgrammer 2010-03-09 09:12:34

+0

我希望避免對鎖定對象進行第二次檢查。我知道,IBM的讀/寫鎖執行允許調用線程升級它的鎖,如果它是唯一擁有寫鎖的線程。 http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/users_93.htm – ScaryAardvark 2010-03-09 09:16:54

+0

@nos。是的,這會陷入僵局。當T1要求升級時將被阻止,因爲T2有一個讀鎖定。當T2保持讀鎖定時,T2將在升級到寫鎖時阻塞。 – ScaryAardvark 2010-03-09 09:24:18

0

最簡單,最安全的是採取從你會想改變的,而不是從目前數據的時刻寫鎖定你相信你會改變它。我知道這將使訪問您的數據更具序列化。

當讀這個問題時我有點驚訝,因爲我從來沒有考慮過先採取了讀鎖,然後升級到寫鎖。那麼,不同的情況可能需要不同的方法。

+2

當你不需要它時,獲得寫鎖定似乎有點過分了。正如你所指出的那樣,這將會連載。而獲取讀鎖不會阻塞。在你知道你需要改變的地方,你可以升級到寫入鎖定。這只是在posix下這樣做的實際行爲,引入了一場比賽,這是一個恥辱。 – ScaryAardvark 2010-03-09 09:21:55

+0

這是一個恥辱,但在大多數情況下,我知道,這是一個理論上的差異。 – stefaanv 2010-03-09 10:26:30

0

我認爲,而不是使用pthread讀/寫鎖,你可以使用posix fcntl()。在這裏,您可以無需任何麻煩地從讀取升級到寫入。我們使用它來插入B樹。一旦我們開始瞭解插入發生的節點,我們會將其升級爲寫入鎖定。另外,當我們需要拆分節點時,我們將升級節點的鎖定,其父節點和子節點從讀取到寫入。由於B-tree是一個基於文件的數據結構,它有助於鎖定文件的區域。