互斥锁和锁

6
下面的两个代码示例是否等价?
Poco::ProcessHandle::PID ProcessRunner::processId() const
{
    Poco::ProcessHandle::PID pid = 0;
    mMutex.lock();
    pid = mPID;
    mMutex.unlock();
    return pid;
}

,

Poco::ProcessHandle::PID ProcessRunner::processId() const
{
    Poco::ScopedLock<Poco::Mutex> lock(mMutex);
    return mPID;
}
  • 在第二个示例中:在返回值副本被创建后,锁是否会超出作用域?如果返回的对象有许多复制指令,则这一点很重要。
  • 如果您只返回一个int值,是否需要锁定?或者int的复制是原子操作吗?
2个回答

8

它们是等价的。局部变量在其块的最后一行被执行之后才会超出作用域。因此,在这种情况下,返回值副本是在锁的保护下完成的。


3
如果Poco的ScopedLock像Boost的lock_guard一样工作,并且PID分配不会抛出异常,那么第一个问题的答案是肯定的。这个ScopedLock的目的是防止死锁。即使在抛出异常的情况下,你也不能忘记解锁互斥量。即使你只是“读取一些数据”,你是否需要锁定呢?嗯,在这种情况下(仅访问一个int),这有点灰色地带(最好不要这样做),但通常情况下,即使你只是读取数据,你也要锁定互斥量。

我更关心操作的原子性。在代码示例2中,哪个先发生:返回值的复制还是锁的销毁?如果不是前者,则这是有缺陷的代码。 - StackedCrooked
据我所知,首先返回值被“构造”,然后所有自动对象都被销毁。 - sellibitze
我刚意识到,如果一个函数返回一个局部变量,在销毁它之前必须先复制它。哎呀。 - StackedCrooked
2
如果PID分配可能会抛出异常,则第二个示例仍然可以正确解锁互斥锁,而第一个示例将保留互斥锁处于锁定状态。+1是指“PID分配不会抛出异常”。 - ChrisInEdmonton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接