Re: синхронизация потоков
От: imerlin  
Дата: 30.05.14 13:59
Оценка:
Здравствуйте, tdiff, Вы писали:

T>Возьмём классический пример синхронизации потоков:



{...}

T>Подобный код приводится в качестве примера ошибочного, т.к. может быть оптимизирован компилятором до


{...}
T>Такая оптимизация возможна, т.к. компилятор видит, что раз внутри work() flag не меняется, поэтому
T>нет смысла считывать его на каждой итерации.


T>Стандартное в практике решение этой проблемы — использовать mutex:

{...}
T>Моё предположение такое: где-то внутри mutex используется какая-то специальная инструкция типа memory barrier, которую компилятор не может позволить себе отоптимизировать.
T>Так ли это? Если да, то что это за инструкция на самом деле?

Насколько я знаю то что Вы написали в качестве "правильного" варианта тоже неверно. Обычно рекомендуется использовать специальные объекты ядра — события, семафоры, мьютексы (я проглядел по диагонали, по моемы Вы под мьютексом понимаете нечто другое). Когда Вы синхронизируетесь с помощью объекта ядра Ваш ждущий поток не крутится в цикле, поедая драгоценное время, а выключается из планировщика потоков и сразу же ставится в очередь как только объект сигнализирует о том, что ожидание закончилось.

То есть схема такая:
//Вы создаете событие в обоих синхронизируемых процессах.
HANDLE hEv=CreateEvent(NULL,FALSE,TRUE,"lalala");
//затем один процесс "засыпает" до окончания работы второго:
WaitForSingleObject(hEv);
//и делает что то дальше
//**********************************
//второй процесс чтото делает
{...}
//по окончании говорит, что момент пришел:
SetEvent(hEv) //именно в этот момент "проснется", то есть вернется из функции WaitForSingleObject первый процесс.

Компилятор, естественно, там ничего оптимизировать и испортить не сможет.

Извините, если не понял Вашего вопроса.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.