class Foo {
public:
// ...
const int &getBar() const noexcept;
void doSomethingWithBar(); // (2)
private:
std::mutex barMutex;
int bar = 7;
};
const int &Foo::getBar() const noexcept {
std::lock_guard<std::mutex> lock(this->barMutex); // (1)
return this->bar;
}
void Foo::doSomethingWithBar() {
std::lock_guard<std::mutex> lock(this->barMutex); // necessary here
this->bar++;
}
就线程安全而言,行1
是必要的,考虑到另一个线程可能会干扰并调用行2
中的函数,从而更改bar
的值?
请注意int
可能是此处的任何类型。
答案 0 :(得分:4)
看到你正在返回一个引用,在这种情况下,锁定对你来说完全没用。当您使用返回的引用时,您可能需要锁定。
但是,如果您返回的值会产生更多影响,请查看this以获取撕裂的示例。
答案 1 :(得分:0)
第1行没有您期望的效果:显然,您尝试锁定对象并在调用者处理返回的引用时将其锁定。
但是你创建的lock_gard是getBar()的本地对象,并在你返回时获得destroyed,从而解锁你刚刚获得的锁。
有几种替代方案,例如:
您可以更改函数以返回bar的值,但要考虑到此值是一个快照,当您使用它时可以过时。
您也可以更改功能以一次性获取和处理条形图(例如,通过提供函数作为参数)。
您还可以将锁作为类成员进行管理,并提供函数releaseBar()以在不再需要时立即解锁互斥锁。然而,这是一种更危险的方法,因为呼叫者可能忘记释放锁定。