Добрый день!
Я не имею большого опыта работы с объектами сихронизации в *nix. Но возникла необходимость реализовать condition variables под Win32 (WinNT). Часто встречаются куски кода типа:
Поток1
{ pthread_mutex_lock(&mutex);
.....
pthread_cond_wait(&condVar, &mutex);
.....
pthread_mutex_unlock(&mutex);
}
Поток 2
{ pthread_mutex_lock(&mutex);
......
pthread_cond_signal(&condVar);
......
pthread_mutex_ulock(&mutex);
}
В связи с этим вопрос: всегда ли оба потока используют один и тотже мьютекс (или может есть ситуации когда несколько потоков могут использовать разные мьютексы)? Это имеет значение при реализации condition variables под Win32.
PS. Не сочтите вопрос глупостью, просто очень мало программировал многопоточность в *nix.
Спасибо за помощь
>Добрый день!
>Я не имею большого опыта работы с объектами сихронизации в *nix. Но
>возникла необходимость реализовать condition variables под Win32 (WinNT). Часто встречаются куски
>кода типа:
>Поток1
> { pthread_mutex_lock(&mutex);
> .....
> pthread_cond_wait(&condVar, &mutex);
> .....
> pthread_mutex_unlock(&mutex);
>}
>Поток 2
> { pthread_mutex_lock(&mutex);
> ......
> pthread_cond_signal(&condVar);
> ......
> pthread_mutex_ulock(&mutex);
> }
>В связи с этим вопрос: всегда ли оба потока используют один и
>тотже мьютекс (или может есть ситуации когда несколько потоков могут использовать
>разные мьютексы)? Это имеет значение при реализации condition variables под Win32.
>
>PS. Не сочтите вопрос глупостью, просто очень мало программировал многопоточность в *nix.
>
>Спасибо за помощьДобрый день
Критическая секция (не путать с Windows CritialSection - это анонимный мьютекс)- это участок кода, который имеет доступ к данным , общим для разных потоков или процессов, выполняющихся "одновременно". Например, 2 потока, пишущих в один файл. Все семафоры, мьютексы, синхро переменные, condition variables, event semaphores используются для "защиты" вышеупомянутых критических секций. Т.к. condition variable ( даже одна из ее частей) по природе может изменяться в разных потоках, то мьютекс должен быть один и тот же. Если у Вас 2 или больше condition variables и они никак не пересекаются, то можно и нужно использовать разные мьютексы (по одному на каждую из condition variables).
Кстати всегда лучше поcылать сигнал ВНЕ мьютекса:
pthread_mutex_lock(&mutex);
...
pthread_mutex_ulock(&mutex);
pthread_cond_signal(&condVar);Это надо потому, что больше шансов, что после сигнала другой поток получит мьютекс для блокировки.
Ксатати на Windows существует уже упомянутые Event Semaphore objects, которые используются для тех же целей, что и condition variables (CreateEvent,OpenEvent, SetEvent, ResetEvent, PulseEvent, WaitForSingleObject, WaitForMultipleObjects ).
Успехов
--- sas
Уважаемый sas! Вы писали:
> Т.к. condition variable ( даже одна
>из ее частей) по природе может изменяться в разных потоках, то
>мьютекс должен быть один и тот же. Если у Вас 2
>или больше condition variables и они никак не пересекаются, то можно
>и нужно использовать разные мьютексы (по одному на каждую из condition
>variables).
>
>Кстати всегда лучше поcылать сигнал ВНЕ мьютекса:
> pthread_mutex_lock(&mutex);
> ...
> pthread_mutex_ulock(&mutex);
> pthread_cond_signal(&condVar);
>
>Это надо потому, что больше шансов, что после сигнала другой поток получит
>мьютекс для блокировки.
Ведь вызов pthread_cond_signal(&condVar); может быть потенциально опасен (напр. произошло переключение контекста и другой поток вызывает pthread_cond_wait(...))Или при вызове не изменяются поля структуры pthread_cond_t? Или эти операции атомарны?>Ксатати на Windows существует уже упомянутые Event Semaphore objects, которые используются для
>тех же целей, что и condition variables (CreateEvent,OpenEvent, SetEvent, ResetEvent, PulseEvent,
>WaitForSingleObject, WaitForMultipleObjects ).Но ведь это не тоже самое, что condition variables (которые всегда используются вместе с мьютексом и операция отпускание_мьютекса-засыпание_на_condVar выполняется атомарно). И если на платформе NT с этим еще можно как-то бороться (с пом. SignalObjectAndWait(...) ) то что делать на 95/98 вообще говоря не совсем ясно. :(
>Уважаемый sas! Вы писали:
>> Т.к. condition variable ( даже одна
>>из ее частей) по природе может изменяться в разных потоках, то
>>мьютекс должен быть один и тот же. Если у Вас 2
>>или больше condition variables и они никак не пересекаются, то можно
>>и нужно использовать разные мьютексы (по одному на каждую из condition
>>variables).
>>
>>Кстати всегда лучше поcылать сигнал ВНЕ мьютекса:
>> pthread_mutex_lock(&mutex);
>> ...
>> pthread_mutex_ulock(&mutex);
>> pthread_cond_signal(&condVar);
>>
>>Это надо потому, что больше шансов, что после сигнала другой поток получит
>>мьютекс для блокировки.
>Ведь вызов pthread_cond_signal(&condVar); может быть потенциально опасен (напр. произошло переключение контекста и
>другой поток вызывает pthread_cond_wait(...))Или при вызове не изменяются поля структуры pthread_cond_t?
>Или эти операции атомарны?"pthread_cond_signal - unblock a thread waiting for a condition variable" Кстати на многих системах проснуться могут больше чем один поток
Единственное что может произойти - это поток проснулся, не смог взять контроль и заснул опять.pthread_cond_t - системно/библиотеко зависимый тип объекта Он может быть указателем или структурой или ... То как он изменяется/используется определяется системой/библиотекой К этому объекту применяются те же правила что и к остальным разделяемым данным (см первый пост) Механизм обеспечения этого - "implementation specific"
Исторически, из-за ошибки в документации к Solaris меньше 2.6, считалось что
pthread_cond_signal должен вызываться изнутри залокированного мьютекса (lost wakeup проблема) На самом деле это не так Кстати я так и не смотрел документацию к Solaris 2.6 или старше чтобы проверить исправлена ли ошибка :)>
>>Ксатати на Windows существует уже упомянутые Event Semaphore objects, которые используются для
>>тех же целей, что и condition variables (CreateEvent,OpenEvent, SetEvent, ResetEvent, PulseEvent,
>>WaitForSingleObject, WaitForMultipleObjects ).
>
>Но ведь это не тоже самое, что condition variables (которые всегда используются
>вместе с мьютексом и операция отпускание_мьютекса-засыпание_на_condVar выполняется атомарно). И если на
>платформе NT с этим еще можно как-то бороться (с пом. SignalObjectAndWait(...)
>) то что делать на 95/98 вообще говоря не совсем ясно.
>:(На самом деле "событийные объекты" (Event Objects) - можно рассматривать как "синонимы" condition variables:
/*** Поток 1 ***/
/* Заснули (nonsignaled state) пока другой поток не вызовет PulseEvent() (wakeup problem) или SetEvent() */
WaitForSingleObject( my_mutex );
while ( condition == FALSE ) {
/* Блокируем "событие" занято*/
ResetEvent( event );
/* другие могут использовать мьютекс */
ReleaseMutex( my_mutex );
/*наш код*//* lost wakeup problem!!! */
WaitForSingleObject( event );
WaitForSingleObject( my_mutex );
}/*** поток 2 ***/
WaitForSingleObject( my_mutex );
condition = TRUE;
ReleaseMutex( my_mutex );
SetEvent( event );К сожалению я давно под Windows не пишу и поэтому
1 Это только скелет кода
2 по поводу 95/98 вообще ничего не помню :(Успехов
--- sas
Добрый день!
Нашел статью по поводу subj : Strategies for Implementing POSIX Condition Variables on Win32 http://www.cs.wustl.edu/~schmidt/win32-cv-1.html, подробно об этом написано.
Большое спасибо за помощь, уважаемый sas.
Всего доброго.