2012-07-30 66 views
0

當線程正在退出時(在其析構函數中)是否有一種自動釋放線程持有的互斥鎖的萬無一失的方法?當線程析構函數運行時自動釋放互斥鎖

我一直在採取的方法是爲每個互斥體創建一個結構,這個互斥體持有保存它的線程的身份,然後在析構函數中掃描這個列表,並且如果任何互斥體匹配正在完成的線程,然後釋放它。但我認爲這實際上有一個競爭條件:如果在鎖定互斥鎖之後但在設置數據結構之前調用析構函數,會發生什麼?

我也看了一下pthread_mutexattr_setrobust_np,但我的理解是np函數是不可移植的,並且我在過去遇到過問題。

作爲參考,每個線程都與TCP/IP連接相關聯,並且響應於通過此連接的請求發生鎖定/解鎖。如果連接異常關閉,我需要清理,即釋放所有的鎖。

+0

「但我在想這實際上有一個競爭條件:如果在鎖定互斥鎖之後但在設置數據結構之前調用析構函數,會發生什麼? - 這聽起來像你已經有一個競爭條件,甚至在試圖添加跟蹤到互斥體之前。如果你在一個對象上調用一個析構函數而另一個線程正在使用這個對象,那麼就有問題了。 – 2012-07-30 20:24:10

+0

好吧,如果我在pthread_mutex_lock中的線程上調用pthread_kill,那麼在析構函數中鎖將被保持或不被獲取,因爲獲取鎖是一個原子操作。 – Michael 2012-07-30 20:56:13

回答

0

我發現了一個似乎可行的解決方案。首先,我使用錯誤檢查互斥鎖(PTHREAD_ERRORCHECK_MUTEX_INITIALIZERPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)。

接下來,在析構函數中,我試圖解鎖所有互斥鎖,並且想法是線程所擁有的任何互斥鎖都將被單獨保留,但線程擁有的任何互斥鎖都將被釋放。

由於某些原因,線程擁有的互斥鎖返回EPERM,但隨後嘗試從另一個線程重新鎖定互斥鎖成功,而未嘗試解鎖另一個嘗試將會死鎖。相反,在析構函數運行後,仍然會發現非析構線程所擁有的其他互斥鎖被鎖定。

+0

你是說dtor與獲取互斥鎖的線程在同一線程上運行?如果是這樣,那麼在解鎖互斥鎖時得到一個'EPERM'就意味着事物不處於你認爲它們的狀態。線程如何在沒有釋放互斥鎖的情況下進入dtor?您可能想要研究取消點和取消清理處理程序。 – 2012-07-30 22:45:34

+0

我假設它。當我從析構函數調用pthread_self()時,它將返回我期望從線程獲得的值。在到達析構函數之前線程沒有釋放互斥體的原因是互斥體是通過TCP連接上的客戶機請求獲取的。 (客戶端實際上正在獲取一個鎖,但鎖是通過互斥鎖實現的)如果連接在客戶端發佈之前就已經死掉,我們必須以某種方式清理(釋放鎖)。 – Michael 2012-07-30 23:12:01

+0

我一直在尋找清理處理程序,但我不知道他們將如何工作,如果他們沒有在與互斥鎖相同的範圍內完成,即他們需要在線程的頂層完成,而互斥鎖可能發生在任何級別的函數嵌套上。 – Michael 2012-07-30 23:23:34