Всем доброго времени суток!
Вопрос такой. Если я завожу некую переменную типа sig_atomic_t. По идее она обеспечивает атомарный доступ к себе. Можно ли при этом сказать, что если её значение изменяют нити, то эти изменения можно не синхронизировать мутексами между этими самыми нитями.
И ещё вопрос, когда нить находится в блокировке мутексом, она совсем совсем не расходует процессорное время, или происходит периодический вызов её шедулером на проверку мутекса.
Заранее спасибо за ответы.
>Всем доброго времени суток!
> Вопрос такой. Если я завожу некую переменную типа sig_atomic_t. По идее
>она обеспечивает атомарный доступ к себе. Можно ли при этом сказать,
>что если её значение изменяют нити, то эти изменения можно не
>синхронизировать мутексами между этими самыми нитями.Она вообще-то немного для других целей (обработка сигналов), но всё же. sig_atomic_t гарантирует, что он будет записан ровно за одну инструкцию.
Можно ли? Я бы сказал, зависит от кода. Например, такой код:
/* где-то глобально */
sig_atomic_t t;/* первая нить */
if(t == 0)
{
t = 1;
}/* вторая нить */
if(t == 0)
{
/* далее идут вычисления, подразумевающие, что t == 0*/
}Тут нужно синхронизировать весь блок if(), потому что возможен такой сценарий:
неважно кто: t = 0;
первая нить: t == 0? да!
вторая нить: t == 0? да!
первая нить: t = 1;
вторая нить: думает что там 0, но там 1> И ещё вопрос, когда нить находится в блокировке мутексом, она совсем
>совсем не расходует процессорное время, или происходит периодический вызов её шедулером
>на проверку мутекса.Нет, нить просто спит не просыпаясь.
>[оверквотинг удален]
>{
> /* далее идут вычисления, подразумевающие, что t == 0*/
>}
>
>Тут нужно синхронизировать весь блок if(), потому что возможен такой сценарий:
>неважно кто: t = 0;
>первая нить: t == 0? да!
>вторая нить: t == 0? да!
>первая нить: t = 1;
>вторая нить: думает что там 0, но там 1Не, ну такая ситаЯция вполне понятна. Я имею ввиду немного другое. Прошу прощение за неправильно поставленный вопрос. Уточняю. Есть некая глобальная переменная типа sig_atomit_t, и нити скопом читающие буфер. Прочитав буфер нить уменьшает значение этой переменной на еденичку. Идея и состоит в том, что бы использовать тип sig_atomic_t не применяя мутексы на эту переменную.
Вооот, и про второй вопрос:
>Нет, нить просто спит не просыпаясь.
вот и я так знаю, что нить спит, пока ей не буде позволено семафором/мутексом двигаться далее. Но.... есть некая книга... "Программирование под UNIX" Марк Дж. Рочкинд.
Приведу отрывок из параграфа о переменных состояния (cond_wait,cond_signal)
Сначала идет некая философия, затем предлагается схема взаимодействия двух потоков. Внимание на экран :)
"
Поток А Поток В
1.Прочитать данные 1.Захватить мутекс "М"
2.Захватить мутекс "М" 2.Если есть данные, извлечь их
3.Поместить очередную 3.Освободить мутекс "М"
порцию данных в буфер 4.Перейти к шагу 1.
4.Освободить мутекс "М"
5.Перейти к шагу 1
"
...вроде бы все хорошо, красиво и замечательно(было бы замечательно использовать ещё и семафор :)). Далее автор пишет
"Этот вариант работает надежно, но поток В расходует слишком много процессорного времени во время ожидания поступления данных в очередь"вот здесь я и подумал ... а как это он расходует время. По идее время расходываться может только тогда, когда он будет крутиться между 1 и 4 так и не попадая в 2. Но ведь попробовав захватить мутекс на шаге 1, он должен заблокироваться если очередь обрабатывается потоком А.
Ну а потом еще философия и автор предлагает следущую схему взаимодействия
Поток А Поток В
1.Прочитать данные 1.Захватить мутекс "М"
2.Захватить мутекс "М" 2.while(queue_is_empty){cond_wait(C,M)}
3.Поместить очередную 3.Если есть данные, извлечь их
порцию данных в буфер 4.Освободить мутекс "М"
4.cond_signal(C) 5.Перейти к шагу 1.
5.Освободить мутекс "М"
6.Перейти к шагу 1Но это уже не по делу..., так вот как же сё таки поток В расходует это самое время
>Есть некая глобальная переменная типа
>sig_atomit_t, и нити скопом читающие буфер. Прочитав буфер нить уменьшает значение
>этой переменной на еденичку. Идея и состоит в том, что бы
>использовать тип sig_atomic_t не применяя мутексы на эту переменную.При условии, что чтение из буфера синхронизируется какими-то другими методами -- то можно.
>"Этот вариант работает надежно, но поток В расходует слишком много процессорного времени
>во время ожидания поступления данных в очередь"Объясняю. Тут получается, что поток А будет ждать на шаге 1, заблокировавшись например на recv(). В это время поток В постоянно выполняет холостой цикл: mutex_lock, нет новых данных, mutex_unlock, и всё заново.
>Ну а потом еще философия и автор предлагает следущую схему взаимодействия
>/* тут идёт схема с cond_wait */Вот это верно, так как тут поток захватит мутекс именно по сигналу, то есть именно когда данные уже есть.
да уж, че то я как то не подумал про первый шаг потока А. Зациклил внимание на потоке В, вот оно так и получилось. :) Спасибо. Все оказалось проще некуда :)