The*_*ist 5 c++ parallel-processing multithreading mutex global-variables
我想问一下有关多线程的最简单的Mutex方法.以下代码是否是线程安全的(快速n-dirty)?
class myclass
{
bool locked;
vector<double> vals;
myclass();
void add(double val);
};
void myclass::add(double val)
{
if(!locked)
{
this->locked = 1;
this->vals.push_back(val);
this->locked = 0;
}
else
{
this->add(val);
}
}
int main()
{
myclass cls;
//start parallelism
cls.add(static_cast<double>(rand()));
}
Run Code Online (Sandbox Code Playgroud)
这有用吗?它是线程安全的吗?我只想了解如何编写最简单的互斥锁.
如果你对我的例子有任何建议,那就太好了.
谢谢.
谢谢你说它不起作用.你能建议一个独立于编译器的修复程序吗?
它是线程安全的吗?
当然不是.如果在检查和设置锁之间抢占线程,则第二个线程可以获取该锁; 如果控制然后返回到第一个线程,那么两者都将获得它.(当然,在现代处理器上,两个或更多内核可以同时执行相同的指令,以获得更多的欢乐.)
至少,您需要一个原子测试和设置操作来实现这样的锁.C++ 11库提供了这样的东西:
std::atomic_flag locked;
if (!locked.test_and_set()) {
vals.push_back(val);
locked.clear();
} else {
// I don't know exactly what to do here;
// but recursively calling add() is a very bad idea.
}
Run Code Online (Sandbox Code Playgroud)
或者更好的是:
std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
vals.push_back(val);
Run Code Online (Sandbox Code Playgroud)
如果你有一个较旧的实现,那么你将不得不依赖于你可以使用的任何扩展/库,因为那时语言或标准库没有任何帮助.
不,这不是线程安全的.之间有一场比赛
if(!locked)
Run Code Online (Sandbox Code Playgroud)
和
this->locked = 1;
Run Code Online (Sandbox Code Playgroud)
如果在这两个语句之间存在上下文切换,则锁定机制会崩溃.您需要原子test and set指令,或者只需使用现有指令mutex.
此代码不提供vals向量的原子修改.请考虑以下情形:
//<<< Suppose it's 0
if(!locked)
{ //<<< Thread 0 passes the check
//<<< Context Switch - and Thread 1 is also there because locked is 0
this->locked = 1;
//<<< Now it's possible for one thread to be scheduled when another one is in
//<<< the middle of modification of the vector
this->vals.push_back(val);
this->locked = 0;
}
Run Code Online (Sandbox Code Playgroud)