我目前正試圖圍繞使用C++ STL容器的線程安全問題來解決我的問題。我最近試圖通過使用std :: mutex作爲成員變量來實現一個線程安全的std :: vector,然後才意識到雖然我可以通過鎖定鎖使成員函數成爲線程安全的,但我無法使lib函數像std :: sort線程安全,因爲它們只能得到begin()/ end()迭代器,這是STL中容器和算法之間基本分離的結果。使用軟件事務存儲器的C++ std :: vector訪問
那麼我想,如果我不能使用鎖,軟件事務內存(STM)如何?
所以現在我堅持這一點:
#include <atomic>
#include <cstdlib>
#include <iostream>
#include <thread>
#include <vector>
#define LIMIT 10
std::atomic<bool> start{false};
std::vector<char> vec;
void thread(char c)
{
while (!start)
std::this_thread::yield();
for (int i = 0; i < LIMIT; ++i) {
__transaction_atomic {
vec.push_back(c);
}
}
}
int main()
{
std::thread t1(thread, '*');
std::thread t2(thread, '@');
start.store(true);
t1.join();
t2.join();
for (auto i = vec.begin(); i != vec.end(); ++i)
std::cout << *i;
std::cout << std::endl;
return EXIT_SUCCESS;
}
我與編譯:
g++ -std=c++11 -fgnu-tm -Wall
使用G ++ 4.8.2,並且給了我以下錯誤:
error: unsafe function call to push_back within atomic transaction
我有點得到,因爲push_back或排序或任何沒有聲明transaction_safe但離開我跟隨問題:
a)如何解決該錯誤?
b)如果我不能解決這個錯誤,那麼這些事務塊通常用於什麼?
c)如何實現一個無鎖線程安全向量?
在此先感謝!
編輯: 感謝迄今的答案,但他們並沒有真正抓我的癢。讓我舉個例子: 想象一下,我有一個全局向量,並且訪問這個向量應該在多個線程之間共享。所有線程都嘗試進行分類插入,因此它們會生成一個隨機數並嘗試以排序的方式將該數插入到矢量中,因此矢量始終保持排序(包括c的重複)。要執行排序的插入,他們使用std :: lower_bound來查找插入的「索引」,然後使用vector.insert()進行插入。
如果我爲包含std :: mutex作爲成員的std :: vector編寫一個包裝,比我可以編寫包裝函數插入使用std :: lock_guard鎖定互斥鎖,然後執行實際的std :: vector.insert()調用。但是std :: lower_bound並不會對成員互斥量產生任何影響。這是一個功能,而不是bug afaik。
這讓我的線程變得非常糟糕,因爲其他線程可以在某人正在做他的lower_bound事情時更改向量。
我能想到的唯一修復方法是:忘記包裝器,而不是全局互斥量。每當有人想對這個向量做任何事情時,他都需要這個鎖。
這樣的問題。使用這個全局互斥體有什麼替代方法。 和那裏軟件交易記憶浮現在腦海。
那麼現在:如何在STL容器上使用STM? (和a),b),c))。
'std :: vector'已經是線程安全的。有關更多詳細信息,請參閱http://stackoverflow.com/questions/9042571/is-stdvector-or-boostvector-thread-safe。 – Nate
Nah ..當我說「線程安全」時,這不是我的意思。我的意思是像真正的線程安全,而不是隻讀廢話。 – user2036087