Closed. This question needs details or clarity. It is not currently accepting answers. Learn more。
想改进这个问题吗?添加细节并通过editing this post澄清问题。
我在c++11中实现了读写器问题…我想知道它出了什么问题,因为这类事情很难自己预测。
共享数据库:
当没有写入程序时,读取器可以访问数据库
当没有读写器时,写入器可以访问数据库
一次只有一个线程操作状态变量
这个例子有三个读写器和一个写器,但也使用两个或更多的写器。。。。
代码:
class ReadersWriters {
private:
int AR; // number of active readers
int WR; // number of waiting readers
int AW; // number of active writers
int WW; // number of waiting writers
mutex lock;
mutex m;
condition_variable okToRead;
condition_variable okToWrite;
int data_base_variable;
public:
ReadersWriters() : AR(0), WR(0), AW(0), WW(0), data_base_variable(0) {}
void read_lock() {
unique_lock<mutex> l(lock);
WR++; // no writers exist
// is it safe to read?
okToRead.wait(l, [this](){ return WW == 0; });
okToRead.wait(l, [this](){ return AW == 0; });
WR--; // no longer waiting
AR++; // now we are active
}
void read_unlock() {
unique_lock<mutex> l(lock);
AR--; // no longer active
if (AR == 0 && WW > 0) { // no other active readers
okToWrite.notify_one(); // wake up one writer
}
}
void write_lock() {
unique_lock<mutex> l(lock);
WW++; // no active user exist
// is it safe to write?
okToWrite.wait(l, [this](){ return AR == 0; });
okToWrite.wait(l, [this](){ return AW == 0; });
WW--; // no longer waiting
AW++; // no we are active
}
void write_unlock() {
unique_lock<mutex> l(lock);
AW--; // no longer active
if (WW > 0) { // give priority to writers
okToWrite.notify_one(); // wake up one writer
}
else if (WR > 0) { // otherwize, wake reader
okToRead.notify_all(); // wake all readers
}
}
void data_base_thread_write(unsigned int thread_id) {
for (int i = 0; i < 10; i++) {
write_lock();
data_base_variable++;
m.lock();
cout << "data_base_thread: " << thread_id << "...write: " << data_base_variable << endl;
m.unlock();
write_unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void data_base_thread_read(unsigned int thread_id) {
for (int i = 0; i < 10; i++) {
read_lock();
m.lock();
cout << "data_base_thread: " << thread_id << "...read: " << data_base_variable << endl;
m.unlock();
read_unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
};
int main() {
// your code goes here
ReadersWriters rw;
thread w1(&ReadersWriters::data_base_thread_write, &rw, 0);
thread r1(&ReadersWriters::data_base_thread_read, &rw, 1);
thread r2(&ReadersWriters::data_base_thread_read, &rw, 2);
thread r3(&ReadersWriters::data_base_thread_read, &rw, 3);
w1.join();
r1.join();
r2.join();
r3.join();
cout << "\nThreads successfully completed..." << endl;
return 0;
}
最佳答案
反馈:1
它缺少所有必需的内容。2
。它假定一个using namespace std
,这是声明中的错误样式,因为它会用名称空间std污染所有客户机。3
。释放锁并不是特别安全的:
write_lock();
data_base_variable++;
m.lock();
cout << "data_base_thread: " << thread_id << "...write: " << data_base_variable << endl;
m.unlock(); // leaked if an exception is thrown after m.lock()
write_unlock(); // leaked if an exception is thrown after write_lock()
4
m.lock()
中的cout
包装实际上是不必要的,因为data_base_thread_write
应该已经提供了独占访问。但是我知道这只是一个演示。write_lock()
我想我在读/写逻辑中看到了一个错误:step 1 2 3 4 5 6
WR 0 1 1 1 0 0
AR 0 0 0 0 1 1
WW 0 0 1 1 1 0
AW 1 1 1 0 0 1
在步骤1中,线程1具有写锁。
在步骤2中,线程2尝试获取读锁,在第二个
5
上递增WR
,并阻塞,等待okToRead
。在步骤3中,线程3尝试获取写锁,在第二个
AW == 0
上递增WW
,并阻塞,等待okToWrite
。在步骤4中,线程1通过将
AW == 0
递减为0来释放写锁,并发出AW
信号。在步骤5中,线程2尽管没有被发出信号,但被错误地唤醒,注意到
okToWrite
,并通过将AW == 0
设置为0和WR
设置为1来获取读锁。在步骤6中,线程3接收信号,注意到
AR
,并通过将AW == 0
设置为0和WW
设置为1来获取写锁。在步骤6中,线程2拥有读锁,线程3(同时)拥有写锁。
AW
类有两个功能:它实现一个读/写互斥锁。
它实现线程执行的任务。
更好的设计将利用在C++ 11中建立的互斥/锁框架。
创建一个包含成员的互斥体:
// unique ownership
void lock(); // write_lock
void unlock(); // write_unlock
// shared ownership
lock_shared(); // read_lock
unlock_shared(); // read_unlock
前两个名称,
6
和ReadersWriters
有目的地与C++ 11互斥类型使用的名称相同。只要做这么多,你就可以做如下事情:std::lock_guard<ReaderWriter> lk1(mut);
// ...
std::unique_lock<ReaderWriter> lk2(mut);
// ...
std::condition_variable_any cv;
cv.wait(lk2); // wait using the write lock
如果你加上:
void try_lock();
然后您还可以:
std::lock(lk2, <any other std or non-std locks>); // lock multiple locks
之所以选择
ReaderWriter
和lock
名字,是因为当前在C++ 1y中的unlock
类型(我们希望y是4)工作草案。它记录在N3659中。然后你可以说:
std::shared_lock<ReaderWriter> lk3(mut); // read_lock
std::condition_variable_any cv;
cv.wait(lk3); // wait using the read lock
也就是说,只要创建一个独立的互斥类型,并为成员函数精心选择名称,就可以实现与std定义的锁、
lock_shared
和锁算法的互操作性。有关此框架的更深入的基本原理,请参见N2406。
08-16 01:59