c ++:互斥,保护和函数调用

时间:2015-11-15 16:29:46

标签: c++ concurrency scope locking mutex

我在想。当我使用std::mutex _lock并希望依靠警卫释放它时,我可以像这样使用它吗?

class MyClass{
private:
    mutable std::mutex _lock;
    void subroutine(){/*...*/}
public:
    void foo(){
        std::lock(_lock);std::lock_guard<std::mutex> g(_lock, std::adopt_lock);
        subroutine();
        //require I still have the lock here
        //...
        return; //g goes out of scope ==> _lock is released
    }
};

或者subroutine的调用是否已经导致锁被释放?如果后者证明是这种情况,我的选择是什么?

更新

这个案子怎么样?

class MyClass{
private:
    mutable std::mutex _lock;
public:
    void subroutine(){ //can be called on its own
        std::lock(_lock);std::lock_guard<std::mutex> g(_lock, std::adopt_lock);
        /*...*/
    }
    void foo(){
        std::lock(_lock);std::lock_guard<std::mutex> g(_lock, std::adopt_lock);
        subroutine();
        //require I still have the lock here
        //...
        return; //g goes out of scope ==> _lock is released
    }
};

1 个答案:

答案 0 :(得分:1)

对子程序的调用不会导致锁被释放。 当std :: lock_guard对象超出范围时(如您在评论中提到的那样),将释放线程在_lock上的锁定。

void foo(){
    std::lock_guard<std::mutex> lg{_lock}; // lock the mutex
    subroutine(); // lock is held here during this call
    // so subroutine must not attempt to lock the mutex _lock!
    return; // lg goes out of scope => its destructor is called which releases the lock on _lock
}

要回答第二个问题,当foo获取_lock锁定然后调用子程序时会出现问题,子程序再次尝试锁定_lock。线程无法获取已锁定的互斥锁上的锁定。我会重新考虑你的课堂设计。如果您绝对必须拥有此设计,则可以执行类似

的操作
void subroutine(bool called_from_foo = false)
{
    if(!called_from_foo)
        std::lock_guard<std::mutex> lg{_lock};
    /* ... */
}

void foo()
{
    std::lock_guard<std::mutex> lg{_lock};
    subroutine(true);
    /* ... */
    return;
}

虽然我不推荐这个,因为以错误的方式使用子程序很容易,导致程序中出现未定义的行为。

如果你发现自己必须在函数之间传递一个锁的所有者,我会看一下std :: unique_lock,因为这个类型是可移动的。