Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Здравствуйте, вы недавно оставляли комментарий к статье про барьер на С++11 (http://habrahabr.ru/post/246947).
Мне кажется, что реализация автора при неудачных обстоятельствах вызывает race condition. Конкретно, если после проверки isNotWaiting в предикате и до вызова wait на unique_lock произойдет вызов notify_all в другом потоке.
В качестве примера: coliru.stacked-crooked.com/a/026144ca755fbde8
К сожалению, на хабре я не зарегистрирован и связаться с автором не могу. Не могли бы вы передать это сообщение автору оригинальной статьи?
not isSomething читается стрёмно.P. S. Несложно из приведённого кода догадаться, что это «одноразовый» барьер: как только через него пройдут все потоки, вы не сможете повторно использовать этот же экземпляр класса в качестве барьера.
class barrier {
const unsigned int threadCount;
std::atomic<unsigned int>threadsWaiting;
std::condition_variable waitVariable;
std::mutex mutex;
public:
barrier(unsigned int n) : threadCount(n) {
threadsWaiting = 0;
}
barrier(const barrier &) = delete;
void wait() {
std::unique_lock<std::mutex> lock(mutex);
if (threadsWaiting.fetch_add(1) >= threadCount - 1) {
threadsWaiting.store(0);
waitVariable.notify_all();
}
else {
waitVariable.wait(lock);
}
}
};
#include <iostream>
#include <vector>
#include <thread>
#include <atomic>
std::atomic<bool> ready(false);
std::atomic<unsigned int> counter(0);
unsigned int MAX_COUNTER = 10000000;
const size_t MAX_THREADS = 50;
void f()
{
while (!ready) {
std::this_thread::yield();
}
while (counter < MAX_COUNTER) {
if (++counter == MAX_COUNTER) {
std::cout << "winner thread #" << std::this_thread::get_id() << std::endl;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<std::thread> threads;
for (size_t i = 0; i < MAX_THREADS; ++i)
threads.push_back(std::thread(f));
ready = true;
for (auto& th : threads) th.join();
std::cout << "counter val = " << counter << std::endl;
getchar();
return 0;
}
Создание барьера синхронизации с использованием C++11