最简单的Mutex.这个例子有用吗?它是线程安全的吗?

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)

这有用吗?它是线程安全的吗?我只想了解如何编写最简单的互斥锁.

如果你对我的例子有任何建议,那就太好了.

谢谢.

谢谢你说它不起作用.你能建议一个独立于编译器的修复程序吗?

Mik*_*our 8

它是线程安全的吗?

当然不是.如果在检查和设置锁之间抢占线程,则第二个线程可以获取该锁; 如果控制然后返回到第一个线程,那么两者都将获得它.(当然,在现代处理器上,两个或更多内核可以同时执行相同的指令,以获得更多的欢乐.)

至少,您需要一个原子测试和设置操作来实现这样的锁.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)

如果你有一个较旧的实现,那么你将不得不依赖于你可以使用的任何扩展/库,因为那时语言或标准库没有任何帮助.


Ola*_*che 5

不,这不是线程安全的.之间有一场比赛

if(!locked)
Run Code Online (Sandbox Code Playgroud)

this->locked = 1;
Run Code Online (Sandbox Code Playgroud)

如果在这两个语句之间存在上下文切换,则锁定机制会崩溃.您需要原子test and set指令,或者只需使用现有指令mutex.


Mak*_*zin 5

此代码不提供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)