2

我想让 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");

我希望如果正在附加字符串,则新请求 appendts(somestring, "appendthis_from_different_thread");将被循环捕获,直到前一个附加完成。

这个解决方案是不是太天真了?

4

1 回答 1

8

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

考虑没有人写过 bool 并且两个线程执行appendts。两者都读取布尔值。现在都可以读真吗?是的!因为在appendtsReadywhile 循环中的读取和下面行中的写入之间有一个微小的延迟!如此之小,它几乎总是可以工作,但是第二个线程的读取可能恰好在该延迟期间发生,因此两者都 read 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具有线程安全性。

我建议使用 astd::lock_guard而不是,mutex.lock(); work(); mutex.unlock();因为它提供了 RAII 的好处,即如果work()返回、抛出或中断或其他任何情况,互斥锁会自动解锁。

于 2013-09-21T16:16:21.190 回答