【发布时间】:2015-01-04 18:14:43
【问题描述】:
我正在尝试实现一个没有互斥锁的线程安全 STL 向量。所以我通过this 发布并为原子原语实现了一个包装器。
但是,当我运行下面的代码时,它从下面的代码中显示了Failed!twice(只有两个竞争条件实例),因此它似乎不是线程安全的。我想知道我该如何解决这个问题?
包装类
template<typename T>
struct AtomicVariable
{
std::atomic<T> atomic;
AtomicVariable() : atomic(T()) {}
explicit AtomicVariable(T const& v) : atomic(v) {}
explicit AtomicVariable(std::atomic<T> const& a) : atomic(a.load()) {}
AtomicVariable(AtomicVariable const&other) :
atomic(other.atomic.load()) {}
inline AtomicVariable& operator=(AtomicVariable const &rhs) {
atomic.store(rhs.atomic.load());
return *this;
}
inline AtomicVariable& operator+=(AtomicVariable const &rhs) {
atomic.store(rhs.atomic.load() + atomic.load());
return *this;
}
inline bool operator!=(AtomicVariable const &rhs) {
return !(atomic.load() == rhs.atomic.load());
}
};
typedef AtomicVariable<int> AtomicInt;
函数和测试
// Vector of 100 elements.
vector<AtomicInt> common(100, AtomicInt(0));
void add10(vector<AtomicInt> ¶m){
for (vector<AtomicInt>::iterator it = param.begin();
it != param.end(); ++it){
*it += AtomicInt(10);
}
}
void add100(vector<AtomicInt> ¶m){
for (vector<AtomicInt>::iterator it = param.begin();
it != param.end(); ++it){
*it += AtomicInt(100);
}
}
void doParallelProcessing(){
// Create threads
std::thread t1(add10, std::ref(common));
std::thread t2(add100, std::ref(common));
// Join 'em
t1.join();
t2.join();
// Print vector again
for (vector<AtomicInt>::iterator it = common.begin();
it != common.end(); ++it){
if (*it != AtomicInt(110)){
cout << "Failed!" << endl;
}
}
}
int main(int argc, char *argv[]) {
// Just for testing purposes
for (int i = 0; i < 100000; i++){
// Reset vector
common.clear();
common.resize(100, AtomicInt(0));
doParallelProcessing();
}
}
有没有像原子容器这样的东西?我还用常规的vector<int> 对此进行了测试,它没有任何Failed 输出,但这可能只是巧合。
【问题讨论】:
-
您的
AtomicVariable不仅毫无意义,而且还非常有害。它需要std::atomic,并使其某些操作成为非原子操作。特别是,std::atomic<int>::operator+=是原子的,而AtomicInt::operator+=不是。
标签: multithreading c++11 containers atomic