有人可以解释一下boost :: upgrade_lock的正确用法。以下代码导致死锁
//Global
typedef boost::shared_mutex Mutex;
typedef boost::shared_lock<Mutex> ReadLock;
typedef boost::upgrade_lock<Mutex> UpgradeLock;
typedef boost::upgrade_to_unique_lock<Mutex> WriteLock;
Mutex sharedMutex;
//Multi threaded reader and writer
{
ReadLock read(sharedMutex);
for (int ii = 0; ii < vec.size(); ++ii) {
Element e = vec[ii];
if (e.needsUpdating()) {
UpgradeLock upgrade(sharedMutex);
WriteLock write(upgrade)
//Do stuff
}
}
}
如果我在升级之前用read.unlock()解锁读锁定,它不会死锁。但似乎这不是必要的吗?
答案 0 :(得分:9)
在boost::shared_mutex
类(实现UpgradeLockable概念)中,单个线程不应尝试同时获取共享和可升级(或唯一)锁。在任何时候,UpgradeLockable都可以拥有N个共享锁(通过lock_shared
)和1个可升级锁(通过lock_upgrade
)。可升级锁可以请求它成为一个唯一的锁,它会阻塞,直到它成为独占持有者,这需要释放所有共享锁。在不释放共享锁的情况下,无法从共享锁转换为唯一锁,或共享锁转换为可升级锁。
请注意,可升级锁不是独占的(可以保留其他共享锁),只是它具有增加其强度的特殊权限。不幸的是,不允许同时使用多个可升级的线程。
在您的情况下,同一个线程正在尝试使用lock_shared
和lock_upgrade
,这将导致死锁。您可以按如下所示重写它,它不会死锁,但它仍然是所有读者的单点争用,因为只有1个一次会保留升级锁。在这种情况下,根据您的其他功能,可能不需要shared_mutex的复杂性。但是,如果其他功能仍在获取共享锁,则下面的内容将按预期执行。
//Multi threaded reader and writer
{
// Only 1 thread can pass this. Other shared locks are also valid
UpgradeLock read(sharedMutex);
for (int ii = 0; ii < vec.size(); ++ii) {
Element e = vec[ii];
if (e.needsUpdating()) {
// Blocks here until all shareds are released
WriteLock write(upgrade)
//Do stuff
}
}
}