2011-01-27 93 views
3

我正在尋找一種類型的鎖,其中持有鎖的線程可以將它傳遞給其選擇的另一個線程。可以從一個線程轉移到另一個線程的鎖

這是爲什麼我想它:

  • 我有類似ConcurrentHashMap類 - 一個專門收集被劃分成多個片段,
  • 大多數修改要求只有一個段被鎖定。少數需要兩個段被鎖定(特別是修改一個鍵,以便它從一個段移動到另一個)。
  • 大多數讀取不需要鎖定 - 易失性讀取通常是足夠的,但偶爾搜索需要鎖定所有(如果修改計數檢查失敗)
  • 搜索在多個線程中完成(通過ThreadPoolExecutor
  • 搜索功能必須具有所有段的一致視圖(例如,它不能錯過一個條目而它正從一個區段移動到另一個區段。)
  • 搜索任務(對於單個區段)可能隨時中斷。

現在我正在考慮在主線程中調用搜索方法並發現需要鎖定所有段的情況。所有的段鎖都必須由主線程立即保存(以確保不存在干擾),但它不是主線程將執行更新 - 它是工作線程之一。因此,我試圖讓主線程「傳遞」鎖定,一旦它知道它具有一致的快照。

我們曾經爲整個集合使用了一個鎖,但隨着它變得更大,對於小的更新而言爭用太多且延遲時間無法接受。

解鎖和重新鎖定(在ReentrantLock上)是不安全的 - 另一個線程可能會在工作線程開始搜索之前修改該段。

一個普通的Semaphore可以處理不同線程的鎖定和解鎖。然後出現的問題是誰應該釋放信號量 - 工作線程需要一種方式來表明它已經取得了鎖的所有權(因爲它可能在此點之前或之後拋出異常,並且主線程需要知道是否清理)這對單元測試來說也很棘手,因爲你永遠不知道信號量獲取或釋放是否發生在正確的線程中。

這將是如果鎖可以在其他方法重入使用的獎金(如果它不是線程之間傳遞。)

我想象和Semaphore的某種組合的AtomicBooleanAtomicReference被調用,但快速谷歌搜索沒有透露任何例子。有什麼理由不使用這種方法?

+2

併發性最適合簡單模型。鑑於描述的長度和模型的複雜性,我建議您嘗試簡化您的要求。恕我直言,它更有可能高效工作。我知道的唯一方法是喚醒特定的線程是Unsafe.park()和Unsafe.unpark(線程),但我不推薦直接使用這些。 – 2011-01-27 07:17:31

+0

如果你想要的只是一個可以傳遞的「鎖」,爲什麼不使用一個令牌傳遞機制,每個段鎖都作爲一個令牌傳遞?如果集合搜索時間足夠長,則此標記甚至可以是文件,充當鎖的文件。主線程可以簡單地將「鎖」賦予工作線程。 – Fakrudeen 2011-01-27 09:55:43

回答

2

反轉使用讀/寫鎖定可能會起作用。在這種習慣用法中,讀鎖保持器對數據結構執行併發寫入(例如,陣列中的獨立時隙)。寫鎖用於獲取獨佔訪問以執行一致的讀取(例如,對數組進行求和)。這是一個很少使用的成語,但在那些古怪的案例中很優雅。你的問題有點難以理解,但這至少可以爲具體解決方案提供一些啓發。我懷疑,如果有更深入的瞭解,問題可以簡化,以便傳統的解決方案更合適。

相關問題