std :: string追加线程安全天真的解决方案?

时间:2013-09-21 16:06:03

标签: c++ string multithreading c++11 stdstring

我想让std :: string追加函数线程安全,因为我追加来自不同线程的特定字符串。

我是c ++的初学者,所以我不确定这会出现什么问题。

我正在考虑的解决方案是使用somestring.append("appendthis");

使用以下代码:

bool appendtsReady = true;
void appendts(std::string& originalString, char* app)
{
    while (!appendtsReady) {}

    appendtsReady = false;
    originalString.append(app);
    appendtsReady = true;
}

appendts(somestring, "appendthis");

我希望如果字符串被追加到新请求中 <{1}}将被循环捕获,直到上一个附加完成。

这个解决方案太天真了吗?

1 个答案:

答案 0 :(得分:8)

这不是线程安全的方式。即使appendtsReady是一个原子布尔(如果你不改变逻辑)!原因如下:

考虑没有人写过bool,两个线程执行appendts。两人都读了博尔。现在可以读到真的吗?是!因为在while循环中读取appendtsReady和在下面的行中写入之间存在微小的延迟!如此微小,它几乎总能工作,但第二个线程的读取可能恰好在延迟期间,所以读取true

解决方案:让他们分享std::mutex

std::mutex mutex;
void appendts(std::string& originalString, char* app)
{
     std::lock_guard<std::mutex> lock(mutex);
     originalString.append(app);
}

现在您可以从两个线程调用此方法,前提是两个线程都知道相同的互斥锁。要么全局声明它(不太好),要么将互斥体的引用传递给两个线程。

std::mutex通过锁定和解锁来工作,就像你想要的布尔变量一样。 但是,std::mutex具有线程安全性。

我建议使用std::lock_guard代替mutex.lock(); work(); mutex.unlock();,因为它提供了RAII的好处,即如果work()返回,抛出或中断或其他什么,互斥锁将自动解锁。