Мне нужно реализовать следующую систему: 1 писатель и 3 читателя во взаимном исключении, но 3 читателя могут читать одновременно. Писатель записывает в общую переменную, называемую dato, случайное число, читатели должны вывести его на консоль. Ожидаемый результат: Я написал: 7; Читаю: 7; Читаю: 7; Я прочитал: 7 Я написал: 1; Читаю: 1; Читаю: 1; Я прочитал: 1 Я написал: 9; Читаю: 9; Читаю: 9; Я прочитал: 9
Я использовал два unique_lock на мьютексе m и две condition_variables: cv1 для читателей (они могут читать, только если писатель уже написал) и cv2 для писателя (он может писать, только если все читатели прочитали).
Чтобы гарантировать параллельное чтение, после ожидания я разблокировал и беру блокировку после инструкции cout. Я думаю, что этот писатель не мог взять блокировку, потому что, когда они читают, он находится в ожидании, а условие opDone == 3 недействительно.
Вместо этого вывод: Я написал: 1 Я прочитал: 1 Я прочитал: Я прочитал: 1 Я прочитал: 1 Я прочитал: 1 1
Это код:
// nreader1writer.cpp : Defines the entry point for the console application.
#include "stdafx.h"
condition_variable cv1, cv2;
mutex m;
volatile atomic_int opDone = 0;
volatile atomic_bool iWrote = false;
volatile atomic_bool flag = false;
volatile atomic_int dato;
void writer();
void reader();
int _tmain()
{
thread t1(reader);
thread t2(reader);
thread t3(reader);
thread t4(writer);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
void writer() {
unique_lock <mutex> ulw (m, defer_lock);
while (opDone.load() != 3); //In this way, writer starts just when all readers are already waiting
ulw.lock();
opDone.store(0);
iWrote.store(false);
while (1) {
dato.store( (int) rand()%10);
cout << "I wrote: " << dato.load() << endl;
iWrote.store(true);
cv1.notify_all();
cv2.wait(ulw, []() {
return (opDone.load() == 3);
});
opDone.store(0);
iWrote.store(false);
}
}
void reader() {
unique_lock <mutex> ulr (m, defer_lock);
ulr.lock();
opDone.fetch_add(1);
while (1) {
cv1.wait(ulr, []() {
return (iWrote.load() == true && opDone.load() < 3);
});
ulr.unlock();
cout << "I read: " << dato << endl;
ulr.lock();
opDone.fetch_add(1);
cv2.notify_one();
}
}
Код отлично работает, если я не разблокирую () перед чтением, но в этом случае операции чтения не параллельны. Есть предложения?