2016-01-25 52 views
2

我知道在C++ 14中可以使用boost::UpgradeLockable
C++ 11有沒有類似的東西?升級讀鎖而不釋放C++ 11中的第一個鎖?

+1

不幸的是,直到c + + 17:http://en.cppreference.com/w/cpp/thread/shared_mutex –

+0

@RichardHodges我不明白這個鏈接是如何相關的。在那個界面中,哪些地方允許鎖升級? – Yakk

+0

@Yakk嗯,你是對的。這就引出了問題,標準建議是否缺少了某些東西,或者是一個可升級的鎖簡單地不必要? –

回答

1

一個可升級的鎖可以寫在更簡單的鎖定基元之上。

struct upgradeable_timed_mutex { 
    void lock() { 
    upgradable_lock(); 
    upgrade_lock(); 
    } 
    void unlock() { 
    upgrade_unlock(); 
    upgradable_unlock(); 
    } 
    void shared_lock() { shared.shared_lock(); } 
    void shared_unlock() { shared.shared_unlock(); } 

    void upgradable_lock() { unshared.lock(); } 
    void ungradable_unlock() { unshared.unlock(); } 

    void upgrade_lock() { shared.lock(); } 
    void upgrade_unlock() { shared.unlock(); } 
private: 
    friend struct upgradable_lock; 
    std::shared_timed_mutex shared; 
    std::timed_mutex unshared; 
}; 

和類似的定時和嘗試變體。請注意,訪問連續兩個互斥鎖的定時變量必須做一些額外的工作以避免花費高達所需時間的兩倍,並且try_lock必須小心第一個鎖的狀態,以防第二個失敗。

然後,你必須寫upgradable_lock,有能力根據請求產生std::unique_lock

當然,這是手寫的線程安全代碼,所以它不太可能是正確的。

在C++ 1z中,您也可以編寫一個不帶時間的版本(使用std::shared_mutexstd::mutex)。


更具體地說,一次只能有一個可升級或寫入鎖定。這就是unshared互斥體所代表的。

只要你持有unshared,沒有其他人正在寫入保護數據,所以你可以從中讀取數據而不必保留共享互斥。

當您想升級時,您可以在共享互斥鎖上獲取唯一的鎖。只要沒有讀者嘗試升級到可升級,這不會發生死鎖。這可以避免讀者閱讀,可以編寫,然後釋放它並返回到只讀狀態(只保存非共享的互斥體)。

+0

這個解決方案是否需要在升級之前尋找一個名爲'shared'的互斥鎖的unique_lock之前先刪除shared_lock?在這種情況下,第二個互斥「非共享」將會是多餘的,或者我錯過了什麼? –

+0

@RichardHodges可升級鎖根本不擁有共享鎖。它只在非共享互斥量上擁有unique_lock。然後它在升級時直接在共享互斥量上獲得unique_lock。這一點就是你在升級時不會失去讀鎖。 – Yakk

+0

明白了,謝謝。 –