2016-01-25 55 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

明白了,谢谢。 –