2013-08-14 2 views
4

Я новичок в C++ (в Windows) и потоковом, и в настоящее время я пытаюсь найти решение своей проблемы с помощью мьютексов, семафоров и событий. Я пытаюсь создать класс Барьера с конструктором и методом Enter. Класс Barrier с его единственным методом Enter должен удерживать любой поток, который входит в него, до тех пор, пока ряд потоков не достигнет этого метода. Количество потоков, ожидающих его получения в контрукторе. Моя проблема заключается в том, как использовать блокировки для создания этого эффекта? мне нужно что-то вроде обратного семафора, который содержит потоки до тех пор, пока счет не будет достигнут, а не как обычные семафоры, которые позволяют потокам до тех пор, пока счет не будет достигнут. Любые идеи относительно того, как это сделать, были бы замечательными. Спасибо, Netanel.C++ Холдинг нескольких потоков

+0

Что вы сделали? – deepmax

+0

Вы хотите использовать потоки C++ 11 или WinAPI? –

+0

@dan - Я использую WinAPI –

ответ

0

ПСЕВДОКОД план может выглядеть следующим образом:

void Enter() 
{ 
    Increment counter (atomically or with mutex) 
    if(counter >= desired_count) 
    { 
     condition_met = true; (protected if bool writes aren't atomic on your architecture) 
     cond_broadcast(blocking_cond_var); 
    } 
    else 
    { 
     Do a normal cond_wait loop-plus-predicate-check (waiting for the broadcast and checking condition_met each iteration to protect for spurious wakeups). 
    } 
} 
1

Может быть:

В CTOR, хранить счетчик предела и создать пустой семафор.

Когда поток вызывает Enter, сначала заблокируйте мьютексы, чтобы вы могли безопасно перемещаться внутри. Включить подсчет потока к счету лимитов. Если предел еще не достигнут, отпустите мьютекс и подождите на семафоре. Если предел достигнут, сообщите о семафоре [limit-1] раз в цикле, обнулите счетчик потоков (готов к следующему разу), отпустите мьютекс и вернитесь из Enter(). Любые потоки, которые ожидали семафора и теперь готовы/работают, должны просто вернуться из своего вызова «Ввод».

Мьютекс предотвращает пропущенную нить, которая вращается вокруг от «входа снова» до тех пор, пока все потоки, которые вызвали «Ввод» и не подождали, были установлены, и барьер сбрасывается.

+0

Я думал о чем-то подобном. Моя проблема заключалась в том, что происходит между выпуском мьютекса и ожиданием семафора.В то время что-то может произойти, как необходимое количество потоков, идущих и освобождающих барьер, заставляя эту нить ждать следующей группы, даже если она прибыла первой ... –

+0

Я не уверен, что вы можете достичь того, чего хотите, Войти(). Если бы каждый поток вызывал функцию Leave(), когда они покидали защищенную область (или собирались все вокруг), вы могли бы построить двухступенчатый барьер, который работал бы так, как вы этого хотите. –

1

Вы можете реализовать его с переменной условия.

Вот пример:

Я объявляю 25 потоков и запускать их делает функцию WorkerThread.

Условие, которое я проверяю, чтобы заблокировать/развязать потоки, равно количеству строк в секции меньше 2. (Я добавил несколько утверждений, чтобы доказать, что делает мой coode).

Мой код просто спит в критической секции и после уменьшения количества потоков в критическом разделе.

Я также добавил мьютекс для сообщений cout, чтобы иметь чистые сообщения. #include #include #include #include #include #include #include/* * утверждает/ использование патезраса;

std::mutex m; 
atomic<int> NumThreadsInCritialSection=0; 
int MaxNumberThreadsInSection=2; 
std::condition_variable cv; 

mutex coutMutex; 

int WorkerThread() 
{ 
    // Wait until main() sends data 
    { 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return NumThreadsInCritialSection<MaxNumberThreadsInSection;}); 
    } 
    assert (NumThreadsInCritialSection<MaxNumberThreadsInSection); 
    assert (NumThreadsInCritialSection>=0); 
    NumThreadsInCritialSection++; 
    { 
     std::unique_lock<std::mutex> lk(coutMutex); 
     cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl; 
    } 

    std::this_thread::sleep_for(std::chrono::seconds(5)); 
    NumThreadsInCritialSection--; 
    { 
     std::unique_lock<std::mutex> lk(coutMutex); 
     cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl; 
    } 

    cv.notify_one(); 
    return 0; 
} 

int main() 
{ 
    vector<thread> vWorkers; 
    for (int i=0;i<25;++i) 
    { 
     vWorkers.push_back(thread(WorkerThread)); 
    } 

    for (auto j=vWorkers.begin(); j!=vWorkers.end(); ++j) 
    { 
     j->join(); 
    } 
    return 0; 
} 

Надеюсь, что это поможет, скажите, если у вас есть какие-либо вопросы, я могу прокомментировать или изменить свой код.

Смежные вопросы