将boost :: shared_lock升级为独占锁

时间:2011-09-11 12:44:58

标签: c++ multithreading boost

有人可以解释一下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()解锁读锁定,它不会死锁。但似乎这不是必要的吗?

1 个答案:

答案 0 :(得分:9)

boost::shared_mutex类(实现UpgradeLockable概念)中,单个线程不应尝试同时获取共享和可升级(或唯一)锁。在任何时候,UpgradeLockable都可以拥有N个共享锁(通过lock_shared)和1个可升级锁(通过lock_upgrade)。可升级锁可以请求它成为一个唯一的锁,它会阻塞,直到它成为独占持有者,这需要释放所有共享锁。在不释放共享锁的情况下,无法从共享锁转换为唯一锁,或共享锁转换为可升级锁。

请注意,可升级锁不是独占的(可以保留其他共享锁),只是它具有增加其强度的特殊权限。不幸的是,不允许同时使用多个可升级的线程。

在您的情况下,同一个线程正在尝试使用lock_sharedlock_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
        }
    }
}