После прохождения this question with the same title и его ответов я решил попробовать что-то, что должно действительно работать только с использованием критической секции и, следовательно, должно быть намного быстрее, чем существующие решения (которые используют другие объекты ядра тоже как мьютекс или семафор)Блокировка чтения/записи с использованием только критического раздела вызывает тупик
Вот мои чтения/запись блокировка/разблокировка функции:
#include <windows.h>
typedef struct _RW_LOCK
{
CRITICAL_SECTION readerCountLock;
CRITICAL_SECTION writerLock;
int readerCount;
} RW_LOCK, *PRW_LOCK;
void InitLock(PRW_LOCK rwlock)
{
InitializeCriticalSection(&rwlock->readerCountLock);
InitializeCriticalSection(&rwlock->writerLock);
}
void ReadLock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->readerCountLock); // In deadlock 1 thread waits here (see description below)
if (++rwlock->readerCount == 1)
{
EnterCriticalSection(&rwlock->writerLock); // In deadlock 1 thread waits here
}
LeaveCriticalSection(&rwlock->readerCountLock);
}
void ReadUnlock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->readerCountLock);
if (--rwlock->readerCount == 0)
{
LeaveCriticalSection(&rwlock->writerLock);
}
LeaveCriticalSection(&rwlock->readerCountLock);
}
int WriteLock(PRW_LOCK rwlock)
{
EnterCriticalSection(&rwlock->writerLock); // In deadlock 3 threads wait here
}
void WriteUnlock(PRW_LOCK rwlock)
{
LeaveCriticalSection(&rwlock->writerLock);
}
А вот функция потока. После звонка InitLock (&g_rwLock);
из main
Я создал ПЯТЬ Нить попробовать эти блокировки.
void thread_function()
{
static int value = 0;
RW_LOCK g_rwLock;
while(1)
{
ReadLock(&g_rwlLock);
BOOL bIsValueOdd = value % 2;
ReadUnlock(&g_rwlLock);
WriteLock(&g_rwlLock);
value ++;
WriteUnlock(&g_rwlLock);
}
}
В идеале этот код должен постоянно работать без проблем. Но к моему разочарованию, он не работает всегда. Иногда он заходит в тупик. Я скомпилировал это и запускал его в Windows XP. Чтобы создавать потоки с помощью threadpool, я использую стороннюю библиотеку. Следовательно, не может дать здесь весь этот код, который включает в себя множество инициализирующих подпрограмм и других вещей.
Но, чтобы сократить историю, мне нравится знать, может ли кто-нибудь взглянуть на приведенный выше код, может указать, что не так с этим подходом?
Я прокомментировал в коде выше, где каждая нить (из FIVE threads) продолжает ждать, когда произойдет взаимоблокировка. (Я нашел это, присоединив отладчик к заторможенному процессу).
Любые входы/предложения были бы действительно замечательными, поскольку я застрял над этим в течение довольно долгого времени (в жадности сделать мой код быстрее, чем когда-либо) ,
Обратите внимание, что это блокировка, зависящая от чтения - если ваш счетчик читателей никогда не достигает 0, запись будет ждать вечно. Если это нежелательно, вы можете подумать о системе продажи билетов, как в [Mellor-Crummey-Scott] (http://www.cs.rochester.edu/u/scott/papers/1991_PPoPP_read_write.pdf) " ярмарка ". –
Как обычно: _RW_LOCK - это имя, зарезервированное для компилятора (ведущее подчеркивание, за которым следует заглавная буква). –
Пожалуйста, разместите * актуальный * код, который демонстрирует проблему. Кодекс здесь явно потерял что-то в переводе и тратит время полезного для людей. –