我有一个关于线程安全这个术语的问题。让我举个例子:
#include <mutex>
#include <vector>
/// A thread-safe vector
class ThreadSafeVector {
private:
std::mutex m;
std::vector<double> v;
public:
// add double to vector
void add(double d) {
std::lock_guard<std::mutex> lg(m);
v.emplace_back(d);
}
// return length of vector
int length() {
std::lock_guard<std::mutex> lg(m);
return v.size();
}
};
你会调用那个类,即它的所有方法,线程安全的吗?
编辑 [CEST 星期日,晚上 9 点]
在获得一些不错的“是的,但是”答案和替代实现之后,我在下面的答案中提供了自己的观点。基本上,它归结为一个简单的问题,一个类的线程安全是否只需要为其方法的并行执行提供强大的原子性和可见性保证,或者一个类是否必须提供超出其自身范围的保证(例如 SERIAL执行)。
恕我直言:
这既安全又有用:
void add(double d) {
std::lock_guard<std::mutex> lg(m);
v.emplace_back(d);
}
这是安全但无用的:
// return length of vector
int length() {
std::lock_guard<std::mutex> lg(m);
return v.size();
}
因为当你得到你的长度时,它很可能已经改变,所以对它的推理不太可能有用。
这个怎么样?
template<class Func>
decltype(auto) do_safely(Func&& f)
{
std::lock_guard<std::mutex> lock(m);
return f(v);
}
这样调用:
myv.do_safely([](auto& vec) {
// do something with the vector
return true; // or anything you like
});
我是一名优秀的程序员,十分优秀!