Я пытался реализовать простой барьер в моем коде, который выглядит следующим образом:Каков правильный способ реализации барьера потока и сброс барьера в C?
void waitOnBarrier(int* barrier, int numberOfThreads) {
atomicIncrement(barrier); // atomic increment implemented in assembly
while(*barrier < numberOfThreads);
}
И тогда есть использование барьера в коде:
int g_barrier = 0; // a global variable
waitOnBarrier(&g_barrier, someKnownNumberOfThreads);
До сих пор так хорошо, но там, где должен Я возвращаю переменную g_barrier обратно к нулю? Если я пишу что-то вроде
g_barrier = 0;
прямо после waitOnBarrier вызова, я буду иметь проблемы, если один из потоков будет выпущен быстрее, чем другие от барьера и свести на нет g_barrier в то время как все другие потоки все еще выполняя петлевые инструкции, поэтому в конечном итоге они будут застрять на барьере навсегда.
Объяснение: waitOnBarrier будет компилировать в нечто вроде этого (псевдокод):
1: mov rax, numberOfThreads
2: mov rbx, [barrier]
3: cmp rax, rbx
4: jmp(if smaller) to 2
Так что, если у нас есть 2 темы с синхронизацией на барьере, и thread_1 медлительность где-то в инструкции 3 или 4 , а более быстрый thread_2 достигает барьера, передает его и продолжается до g_barrier поток аннулирования. Это означает, что после thread_1 достигнет инструкции 2, он увидит нулевое значение на [барьер] и навсегда застрянет на барьере!
Вопрос в том, как я должен аннулировать g_barrier, какое место для него в коде «достаточно далеко», что я могу быть уверен, что к тому времени все потоки покинули барьер? Или есть более правильный способ реализации барьера?
Есть ли причина, по которой вы не хотите использовать библиотеку синхронизации потоков, поставляемую с вашей операционной системой? – ArjunShankar
Да, мой код работает в определенной среде, а не в обычной ОС. – user1483597
И есть ли какая-то конкретная причина для внедрения этой блокировки? – ArjunShankar