я реализовал спин-блокировку с C++ 11 атомной библиотекой:Почему спин-блокировка с std :: memory_order_relaxed выполняется правильно?
class SpinLock {
atomic_bool latch_;
public:
SpinLock() :latch_(false){
}
void lock() {
while(tryLock() == false);
}
bool tryLock() {
bool b = false;
return latch_.compare_exchange_weak(b,true,std::memory_order_relaxed);
}
void unlock() {
latch_.store(false,std::memory_order_relaxed);
}
};
Я проверил правильность порождая несколько потоков следующим образом:
static int z = 0;
static SpinLock spinLock;
static void safeIncrement(int run) {
while(--run >= 0) {
std::lock_guard<SpinLock> guard(spinLock);
++z;
}
}
static void test(int nThreads =2) {
std::vector<std::thread*> workers(nThreads);
z = 0;
for(auto& ptr : workers) ptr = new std::thread(safeIncrement,1<<20);
for(auto ptr : workers) ptr->join();
cout<<"after increment: " <<z << " out of " << (1<<20) * nThreads<<endl;
for(auto ptr : workers) delete ptr;
}
int main() {
test(4);
return 0;
}
Я удивлен, общее в конце добавляет как правильное значение с расслабленным порядком. В этой статье: http://en.cppreference.com/w/cpp/atomic/memory_order, расслабленный порядок означает «нет ограничений синхронизации или порядка», поэтому изменение от одного потока не должно быть видимым от других, не так ли? Почему все еще правильно?
(Тест выполняется на Intel (R) ядро (TM) i5-3337U CPU @ 1.80GHz)
EDIT: (благодаря комментарий Максима) Обновлен код: инициализирует член данных в SpinLock, и обновление тестового кода.
Обеспечить полный исходный код. –
Нет инициализации 'SpinLock :: latch_', его начальное значение является неопределенным. –