Много читателей и один писатель
В много-поточном приложении довольно часто возникает необходимость синхронизировать обращение к разделяемому ресурсу, который могут одновременно читать несколько потоков “читателей”, а производить запись в этот ресурс может только один поток “писатель”. Когда читатели читают данные, то писатель не может писать и должен ждать, пока все читатели не закончат чтение. Когда писатель пишет, то все читатели должны ждать, пока он не запишет все данные и не освободит ресурс.
Ниже приведена моя реализация “читателя” и “писателя”. В этой реализации есть допущение о том, что нам известно максимальное количество читателей MAX_READERS.
|
Обращаю внимание на использование Interlocked-функций. Это такие функции, которые обеспечивают атомарность.
Например, InterlockedIncrement(&gCounter) - это атомарное увеличение на 1 (инкремент) значения gCounter.
Вообще, операция инкремента gCounter не атомарна, она состоит из следующих 3-х операций:
1. прочитать значение из памяти по адресу &gCounter
2. увеличить значение на 1
3. записать результат в память по адресу &gCounter
Если выполняется параллельно 2 потока, то возможна такая ситуация :
[поток 1] читает gCounter, прочитан 0
[поток 2] читает gCounter, прочитан 0
[поток 1] увеличивает значение на 1, получается 1
[поток 2] увеличивает значение на 1, получается 1
[поток 1] записывает 1 в gCounter
[поток 2] записывает 1 в gCounter
В итоге в gCounter будет 1, а не 2, как можно было бы предположить.
UPD. LockLib - классы C++ для блокировки разделяемых ресурсов: http://blog.coolsoftware.ru/2013/12/locklib.html
===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru