[英]Understanding and avoiding the dangers of nested locks in multithreaded applications
對於多線程我還是很陌生,但是已經被燒了好幾次了。 現在,我嘗試避免一些陷阱,但是我很難做到以下幾點:
考慮幾個線程,線程A
生產者,因此是writer
,線程B
, C
,...消費者線程,因此是reader
。 全部共享一個公共緩沖區S
一些基礎書籍建議針對這種情況引入一個所謂的ReadWriteLock
。 可以進行多個並發讀取,但顯然只有一次寫入。Boost也提供了這樣的鎖,Qt也是如此。
讓我們假設兩個函數f1和f2鎖定S進行讀取。 在線程B
中,調用f1並讀取鎖定,而在f1內調用f2再次讀取鎖定 ,因此可以進行嵌套鎖定 。
現在考慮執行f1並首次鎖定讀取的瞬間。 如果線程A被調用並想寫,他將被阻塞。 另外,如果里面F1 F2被調用,並希望將其鎖定不能因為阻塞writer
在等待,在這種情況下,許多鎖(如QReadWriteLock
)阻止進一步的readers
也是如此。 因此,我們得到一個非常討厭的死鎖,該死鎖是無法預測的,並且僅當writer
在f1的鎖和f2的鎖之間插入時才會發生。
我當前避免此類錯誤的方法是調試工具,該工具跟蹤鎖定並斷言同一線程是否試圖鎖定兩次以進行讀取,但這非常麻煩。 除此之外,我避免將太多代碼放在鎖中,這雖然有幫助,但我的團隊的其他成員可以忽略它。
還有什么其他功能可以用來防止這種情況? 為什么ReadWriteLocks完全允許它們? 在設計階段是否有一些通用的經驗法則可以避免上述情況?
預先感謝您閱讀冗長的問題;-)
也許您可以使用QReadWriteLock的tryReadLock函數。 防止死鎖。
如果它無法鎖定讀取文件,則解鎖讀取互斥鎖。
在某些情況下,它可能會丟失要讀取的數據,如果您不想丟失任何要讀取的數據,則可以通過放置標志或ID號或標識失敗的讀取作業並將其放入堆棧的方式來解決,因此寫線程完成工作后,您將能夠從失敗的內容開始恢復讀的內容。 它將使您最大程度地減少數據丟失。
我希望這會有所幫助。
抱歉我的英語不好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.