我们发现在代码中有几个地方,并发读取受互斥锁保护的数据相当普遍,而写入却很少。我们的测量似乎表明,使用简单的互斥锁会严重影响代码读取该数据的性能。因此,我们需要的是一个多读/单写互斥锁。我知道这可以建立在更简单的原语之上,但是在尝试这一点之前,我宁愿要求现有的知识:

有什么批准的方法可以从更简单的同步原语中构建多读/单写锁定?

我确实有一个想法,但是我宁愿得到我(可能是错误地)想出的没有偏见的答案。 (注意:我期望的是一种解释方法,可能是伪代码,而不是完整的实现。我当然可以自己编写代码。)

注意事项:

  • 这需要具有合理的性能。 (我要记住的是,每次访问都需要进行两次锁定/解锁操作。现在这可能还不够好,但是需要其中许多操作似乎是不合理的。)
  • 通常,读取数量很多,但是写入比读取更重要,并且对性能更敏感。读者切不可饿死作家。
  • 我们停留在一个较旧的嵌入式平台(VxWorks 5.5的专有变体)上,并使用一个较旧的编译器(GCC 4.1.2)和boost 1.52 –除了大部分boost的部分依赖POSIX之外,因为POSIX并不完全在该平台上实现。可用的锁定原语基本上是几种信号量(二进制,计数等),在这些信号量之上,我们已经创建了互斥量,条件变量和监视器。
  • 这是IA32,单核。
  • 最佳答案

    似乎只有互斥量和condition_variable作为同步原语。因此,我在这里写了一个读写器锁,使读者感到饥饿。它使用一个互斥锁,两个conditional_variable和三个整数。

    readers - readers in the cv readerQ plus the reading reader
    writers - writers in cv writerQ plus the writing writer
    active_writers - the writer currently writing. can only be 1 or 0.
    

    它以这种方式使读者感到饥饿。如果有几位作家想写作,那么直到所有作家都完成写作之后,读者才有机会阅读。这是因为以后的读者需要检查writers变量。同时,active_writers变量将保证一次只能有一个写程序可以写。
    class RWLock {
    public:
        RWLock()
        : shared()
        , readerQ(), writerQ()
        , active_readers(0), waiting_writers(0), active_writers(0)
        {}
    
        void ReadLock() {
            std::unique_lock<std::mutex> lk(shared);
            while( waiting_writers != 0 )
                readerQ.wait(lk);
            ++active_readers;
            lk.unlock();
        }
    
        void ReadUnlock() {
            std::unique_lock<std::mutex> lk(shared);
            --active_readers;
            lk.unlock();
            writerQ.notify_one();
        }
    
        void WriteLock() {
            std::unique_lock<std::mutex> lk(shared);
            ++waiting_writers;
            while( active_readers != 0 || active_writers != 0 )
                writerQ.wait(lk);
            ++active_writers;
            lk.unlock();
        }
    
        void WriteUnlock() {
            std::unique_lock<std::mutex> lk(shared);
            --waiting_writers;
            --active_writers;
            if(waiting_writers > 0)
                writerQ.notify_one();
            else
                readerQ.notify_all();
            lk.unlock();
        }
    
    private:
        std::mutex              shared;
        std::condition_variable readerQ;
        std::condition_variable writerQ;
        int                     active_readers;
        int                     waiting_writers;
        int                     active_writers;
    };
    

    10-01 09:08