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()

4m.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

前两个名称,6ReadersWriters有目的地与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

之所以选择ReaderWriterlock名字,是因为当前在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