Я пытаюсь реализовать потокобезопасный вектор 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+=
- нет. - person Igor Tandetnik   schedule 04.01.2015