Синхронизация Windows на нескольких мьютексах

Мне это не ясно, может ли кто-нибудь подтвердить это для меня?

У меня следующая проблема с синхронизацией. У меня есть следующие объекты:

A. Process 1, thread 1: Read & write access to the resource.
B. Process 1, thread 2: Read access to the resource.
C. Process 2, thread 3: Read access to the resource.

А вот и условия доступа:

  1. A должен быть заблокирован, пока B или C включены.
  2. B должен быть заблокирован только при включенном A.
  3. C должен быть заблокирован только при включенном A.

Поэтому я подумал использовать для этого 2 именованных мьютекса:

  • hMutex2 = используется для выполнения условия 2 выше.
  • hMutex3 = используется для выполнения условия 3 выше.
  • hStopEvent = событие остановки (необходимо остановить поток, если приложение закрывается).

Итак, для А:

HANDLE hHandles[3] = {hMutex2, hMutex3, hStopEvent};
DWORD dwRes = WaitForMultipleObjects(3, hHandles, FALSE, INFINITE);
if(dwRes == WAIT_OBJECT_0 + 2)
{
    //Quit now
    return;
}
else if(dwRes == WAIT_OBJECT_0 + 0 ||
    dwRes == WAIT_OBJECT_0 + 1)
{
    //Do reading & writing here
    ...

    //Release ownership
    ReleaseMutex(hMutex2);
    ReleaseMutex(hMutex3);
}
else
{
    //Error
}

Для Б:

DWORD dwRes = WaitForSingleObject(hMutex2, INFINITE);
if(dwRes == WAIT_OBJECT_0)
{
    //Do reading here
    ...

    //Release ownership
    ReleaseMutex(hMutex2);
}
else
{
    //Error
}

Для С:

DWORD dwRes = WaitForSingleObject(hMutex3, INFINITE);
if(dwRes == WAIT_OBJECT_0)
{
    //Do reading here
    ...

    //Release ownership
    ReleaseMutex(hMutex3);
}
else
{
    //Error
}

Может ли кто-нибудь подтвердить это:

  • При вызове WaitForMultipleObjects для обоих мьютексов они оба становятся сигнальными (или блокируются)?
  • Также мне нужно освободить оба мьютекса?

person ahmd0    schedule 09.06.2012    source источник
comment
Вы хотите блокировку чтения-записи. И если память не изменяет, то можно обойтись и без WaitForMultipleObjects. (Вам, вероятно, понадобится WaitFSO). Я посмотрю, смогу ли я откопать реализацию этого позже сегодня. До тех пор Bing для блокировки чтения и записи   -  person selbie    schedule 09.06.2012


Ответы (3)


Вызов WaitForMultipleObjects как написано (FALSE для 3-го параметра) будет возвращаться, когда сигнализируется любой из мьютексов. Это означает, что и писатель, и один из читателей могли получить одновременный доступ к ресурсу. Один читатель может обращаться к ресурсу, в то время как другой читатель освобождает свой мьютекс. В этот момент писателя отпускают.

Таким образом, чтобы использовать оба мьютекса таким образом, вам нужно будет ждать их обоих. Однако вы не можете просто установить для этого третьего параметра значение TRUE, так как это будет означать, что для освобождения этого потока потребуется сигнализировать hStopEvent (что, очевидно, нежелательно).

Одна из возможностей может состоять в том, чтобы проверить, какой мьютекс был освобожден, а затем заставить автора записи дождаться другого, прежде чем продолжить. Затем ему нужно будет освободить их обоих после завершения своей задачи. Проблема с этим типом решения заключается в том, что оно может начать усложняться в спешке, и если вы добавите больше процессов, которым нужны мьютексы, вы можете попасть в тупик, если не будете осторожны. Использование блокировки типа чтения-записи немного упростило бы обработку.

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

person Mark Wilkins    schedule 09.06.2012
comment
Спасибо за объяснение. Все это имеет смысл. Думаю, теперь я попытаюсь найти блокировку чтения-записи для WinAPI. Я рад, что разместил его здесь до того, как начал его реализовывать... - person ahmd0; 09.06.2012
comment
Я бы предположил, что есть некоторые доступные, но у меня нет рекомендаций. В конце концов я написал блокировку чтения-записи для C на основе презентации, на которой присутствовал Джеффри Рихтер. Вероятно, было глупо писать свою собственную, но она была проверена моими коллегами и используется, может быть, 10 лет... так что я думаю, что она работает. Однако я бы не советовал писать самостоятельно. Очень легко ошибиться. Тогда я не смог найти общедоступную программу, которая работала бы на трех разных ОС, с которыми мне приходилось иметь дело в то время. - person Mark Wilkins; 09.06.2012
comment
В моем случае чтение происходит намного чаще, чем запись, поэтому это действительно замедлит работу, если я просто использую один мьютекс для всех них. Что касается поиска реализации для этой блокировки чтения-записи, все, что я продолжаю получать, это когда они используют критические секции и не имеют возможности остановить ожидающие потоки с помощью моего подхода остановки событий. - person ahmd0; 09.06.2012

То, что вы ищете, это блокировка чтения-записи. В вашем алгоритме есть одна серьезная проблема - голодание процесса A: если B и C продолжают работать и брать свои мьютексы, A может не войти.

person Greg    schedule 09.06.2012

На самом деле, я могу возразить. WaitForMultipleObjects с параметром waitAll, установленным на FALSE, вернется, если будет сигнализирован какой-либо объект. Вот документация :) Установите для него значение TRUE, и он будет ожидать всех объектов.

Однако ваше решение плохо масштабируется: добавьте еще один поток чтения, и вы застряли с третьим мьютексом...

Однако проблема Writer/Readers уже решалась много раз; почему бы не взглянуть на существующие реализации? Сэкономит вам много времени на отладку, особенно если вы еще не знакомы с API синхронизации Windows. (Тизер: потоки posix имеют блокировку чтения и записи, а boost — shared_mutex.)

person xtofl    schedule 09.06.2012
comment
Как отмечено в комментарии Марка, установка TRUE не работает, потому что это также будет ждать hStopEvent. - person Raymond Chen; 09.06.2012
comment
@RaymondChen: действительно; Я признаю, что «чего вы хотите» несколько чрезмерно оптимистично :) - person xtofl; 09.06.2012
comment
Итак, есть идеи, какие WinAPI использовать для блокировки чтения и записи? - person ahmd0; 09.06.2012
comment
Лично: без опыта. Boost имеет межпроцессную библиотеку, содержащую мьютексы: boost.org/doc/libs/1_49_0/doc/html/interprocess/ - person xtofl; 09.06.2012