2013-09-21 46 views
2

我想使std :: string append函数线程安全,因为我从不同的线程附加了特定的字符串。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");将闻风循环直到前一个追加完成。

这个解决方案太幼稚了吗?

+2

为对象提供锁定。例如。 http://en.cppreference.com/w/cpp/thread/mutex – Aleph

+2

一致性编译器的优化器可以自由地断定while语句的条件永远不会是真的,并删除那些代码。 – IInspectable

+0

是的。将“挥发性”添加到标志可能会有帮助,但正确的锁定会更好。 –

回答

8

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

考虑没有人曾经写到布尔和两个线程执行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()返回,抛出或中断等等,互斥锁会自动解锁。

+0

您可以通过测试和设置使原子标记版本工作。但是互斥体更好。 –

+1

@AlanStokes对,我想说的只是说“它是原子的,它是线程安全的”是不够的,因为逻辑仍然需要不同。我已经添加了一些更清晰的,谢谢! – stefan