简体   繁体   中英

question about std::shared_mutex: threads/reader can‘t read variable at the same time

here is my code

#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <windows.h>

using namespace std;
class Counter {
public:
    Counter() : value_(0) {
    }

    // Multiple threads/readers can read the counter's value at the same time.
    std::size_t Get() const {
        std::shared_lock<std::shared_mutex> lock(mutex_);
        std::cout << std::this_thread::get_id() << ' ' << value_ << std::endl;
        Sleep(1000);
        return value_;
    }

    // Only one thread/writer can increment/write the counter's value.
    void Increase() {
        // You can also use lock_guard here.
        std::unique_lock<std::shared_mutex> lock(mutex_);
        value_++;
        lock.unlock();
    }

private:
    mutable std::shared_mutex mutex_;
    std::size_t value_;
};



void Worker(Counter& counter) {
    counter.Get();
    counter.Increase();
    counter.Get();
}

#include <vector>
int main() {
    Counter counter;
    std::vector<std::thread> v;
    for(int i(0);i<10;i++){v.emplace_back(&Worker, std::ref(counter));}
    for (std::thread& t : v) t.join();
    return 0;
}

And the result is like this:

12188457610048 10196 06744
3692  0011812 8392 6912  00
10392 00
0

0
0



6744 1
3692 2
11812 3
10048 4
4576 5
10392 6
8392 7
10196 8
12188 9
6912 10

It is pretty weird:at the first time I run "counter.Get()",all the reader thread are reading at the same time.But the second time,run "counter.Get()" again after using "counter.Increase()",all the reader thread just have to wait 1 sec to get the answer.Why is that?Is there anything I can do to fix that?

Because link

If one thread has acquired the shared lock (through lock_shared, try_lock_shared), no other thread can acquire the exclusive lock, but can acquire the shared lock.

First Get runs concurrently for all workers, because only shared_lock is acquired. However, Increase operation requires exclusive lock. Now, after releasing exclusive lock from Increase operation you immediately acquire shared lock in second Get operation, which causes all threads that did not call Increase yet to wait 1sec until Get releases the lock.

After a writer releases lock, the chances which thread takes the mutex are not equal, so the same thread is likely to take it again in your case. As reader takes mutex, writers keep waiting.

This is called unfair . In contrast, fair mutex would have given some chance to other threads.

C++ Standard does not define whether C++ mutexes are fair or unfair.

Typically they are unfair, as unfair mutexes are usually better for performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM