2013-09-21 68 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