读者/编写者在C ++ 11中进行多线程处理

时间:2016-06-06 22:20:36

标签: c++ multithreading c++11 mutex stdthread

我试图用std :: thread在C ++中实现一个读者编写器解决方案。

我创建了几个在无限循环中运行的读取器线程,在每次读取访问之间暂停一段时间。我试图重新创建Tanenbaum的“操作系统”一书中提出的算法:

    rc_mtx.lock(); // lock for incrementing readcount
    read_count += 1;
    if (read_count == 1) // if this is the first reader
        db_mtx.lock(); // then make a lock on the database
    rc_mtx.unlock();

    cell_value = data_base[cell_number]; // read data from database
    rc_mtx.lock();
    read_count -= 1; // when finished 'sign this reader off'
    if (read_count == 0) // if this was the last one
        db_mtx.unlock(); // release the lock on the database mutex
    rc_mtx.unlock();

当然,问题是可能满足最后一个读者条件(因此想要解锁)的线程从未获得db_mtx。 我试图打开另一位母亲'线程供读者照顾 获取和释放互斥锁,但在此过程中我迷失了方向。 如果有一种优雅的方法可以克服这个问题(线程可能会尝试以优雅的方式发布一个从未获得过的互斥锁),我很乐意听到!

1 个答案:

答案 0 :(得分:4)

如果读者正在进行中,您可以使用条件变量暂停编写器,而不是使用单独的锁。

// --- read code
rw_mtx.lock();    // will block if there is a write in progress
read_count += 1;  // announce intention to read
rw_mtx.unlock();
cell_value = data_base[cell_number];
rw_mtx.lock();
read_count -= 1;  // announce intention to read
if (read_count == 0) rw_write_q.notify_one();
rw_mtx.unlock();

// --- write code
std::unique_lock<std::mutex> rw_lock(rw_mtx);
write_count += 1;
rw_write_q.wait(rw_lock, []{return read_count == 0;});
data_base[cell_number] = cell_value;
write_count -= 1;
if (write_count > 0) rw_write_q.notify_one();

这种实现具有公平性问题,因为新读者可以在等待作者面前切入。一个完全公平的实现可能会涉及一个适当的队列,允许新读者等待等待的作者,新的作家等待任何等待的读者。

在C ++ 14中,您可以使用shared_timed_mutex代替mutex来实现多个读者/单个作者访问。

// --- read code
std::shared_lock<std::shared_timed_mutex> read_lock(rw_mtx);
cell_value = data_base[cell_number];

// --- write code
std::unique_lock<std::shared_timed_mutex> write_lock(rw_mtx);
data_base[cell_number] = cell_value;

在下一个C ++标准(可能是C ++ 17)中可能会有一个简单的shared_mutex实现。