我需要实现以下系统:1位作家和3位读者互斥,但3位读者可以同时阅读。编写器在一个称为dato的共享变量上写入一个随机数,读者必须将其打印到控制台。预期的输出是:我写道:7; 我读:7; 我读:7; 我读:7我写道:1;我读:1; 我读:1; 我读:1我写道:9;我读:9; 我读:9; 我读:9
我在互斥锁m上使用了两个unique_lock和两个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();
}
}
如果我在读取之前不解锁(),则代码可以完美运行,但是通过这种方式,读取操作不是并行的。有什么建议吗?
看一下原子变量的初始化。例如发出警告。
volatile atomic_int opDone = 0;
// error: copying variable of type 'atomic_int' (aka '__atomic_base') invokes deleted constructor
工作草案(当前为N4527)在第8.5.15节中规定了以下内容。
以 大括号或等于初始化器或条件(6.4)的=形式进行的初始化,以及参数传递,函数返回,引发异常(15.1),处理异常(15.3)和聚合成员的形式初始化(8.5.1)称为复制初始化。[注意:复制初始化可能会调用移动(12.8)。—尾注]
原因是您无法复制原子。所有加载和存储都必须通过显式调用进行。对以下方法的修复应解决此问题:
static atomic_int opDone(0);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句