How to make a multiple-read/single-write lock from more basic synchronization primitives?

后端 未结 8 756
[愿得一人]
[愿得一人] 2020-11-29 17:45

We have found that we have several spots in our code where concurrent reads of data protected by a mutex are rather common, while writes are rare. Our measurements seem to s

8条回答
  •  独厮守ぢ
    2020-11-29 18:16

    It seems like you only have mutex and condition_variable as synchronization primitives. therefore, I write a reader-writer lock here, which starves readers. it uses one mutex, two conditional_variable and three integer.

    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.
    

    It starve readers in this way. If there are several writers want to write, readers will never get the chance to read until all writers finish writing. This is because later readers need to check writers variable. At the same time, the active_writers variable will guarantee that only one writer could write at a time.

    class RWLock {
    public:
        RWLock()
        : shared()
        , readerQ(), writerQ()
        , active_readers(0), waiting_writers(0), active_writers(0)
        {}
    
        void ReadLock() {
            std::unique_lock lk(shared);
            while( waiting_writers != 0 )
                readerQ.wait(lk);
            ++active_readers;
            lk.unlock();
        }
    
        void ReadUnlock() {
            std::unique_lock lk(shared);
            --active_readers;
            lk.unlock();
            writerQ.notify_one();
        }
    
        void WriteLock() {
            std::unique_lock lk(shared);
            ++waiting_writers;
            while( active_readers != 0 || active_writers != 0 )
                writerQ.wait(lk);
            ++active_writers;
            lk.unlock();
        }
    
        void WriteUnlock() {
            std::unique_lock 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;
    };
    

提交回复
热议问题