C++14 读写锁std::shared_mutex的用法

C++11中的互斥量

互斥量说明
std::mutex独占的互斥量,不能递归使用
std::timed_mutex有超时功能的独占互斥量,不能递归使用
std::recursive_mutex递归互斥量,能递归使用
std::recursive_timed_mutex有超时功能的递归互斥量

C++14中引入std::shared_mutex

  • std::shared_mutex用于管理可转移和共享所有权的互斥对象,适用场景比较特殊:一个或多个读线程同时读取共享资源,且只有一个写线程来修改这个资源,这种情况下才能从shared_mutex获取性能优势(Shared mutexes are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so.
  • VC第一个支持shared_mutex的版本是VS2015 update2
  • http://en.cppreference.com/w/cpp/thread/shared_mutex

互斥量管理类-锁

  • shared_lock是read lock。搭配std::shared_mutex使用,被锁后仍允许其他线程执行同样被shared_lock的代码。
  • lock_guard和unique_lock是write lock。被锁后不允许其他线程执行被shared_lock或unique_lock的代码。
  • 通常我们这样定义:
typedef std::shared_lock<std::shared_mutex> ReadLock;
typedef std::lock_guard<std::shared_mutex> WriteLock;

std::shared_mutex和std::mutex的性能对比

// C++_Shard_Mutex_Sample.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <list>
#include <iostream>
#include <vector>

#define READ_THREAD_COUNT 8  
#define LOOP_COUNT 5000000  

typedef std::shared_lock<std::shared_mutex> ReadLock;
typedef std::lock_guard<std::shared_mutex> WriteLock;
typedef std::lock_guard<std::mutex> NormalLock;

class shared_mutex_counter {
public:
    shared_mutex_counter() = default;

    unsigned int get() const {
        ReadLock lock(mutex);
        return value;
    }

    void increment() {
        WriteLock lock(mutex);
        value++;
    }

private:
    mutable std::shared_mutex mutex;
    unsigned int value = 0;
};

class mutex_counter {
public:
    mutex_counter() = default;

    unsigned int get() const {
        NormalLock lock(mutex);
        return value;
    }

    void increment() {
        NormalLock lock(mutex);
        value++;
    }

private:
    mutable std::mutex mutex;
    unsigned int value = 0;
};

class timers
{
public:
    timers()
    {
        m_begin = std::chrono::high_resolution_clock::now();
    }

    ~timers()
    {
        m_end = std::chrono::high_resolution_clock::now();
        Consuming();
    }

    void Consuming()
    {
        std::cout << "Time-consuming:" << std::chrono::duration_cast<std::chrono::duration<float, std::milli>>(m_end - m_begin).count() << std::endl;
    }

private:
    std::chrono::high_resolution_clock::time_point m_begin;
    std::chrono::high_resolution_clock::time_point m_end;
};


void test_shared_mutex()
{
    shared_mutex_counter counter;
    unsigned int temp;

    auto writer = [&counter]() {
        for (unsigned int i = 0; i < LOOP_COUNT; i++){
            counter.increment();
        }
    };

    auto reader = [&counter, &temp]() {
        for (unsigned int i = 0; i < LOOP_COUNT; i++) {
            temp = counter.get();
        }
    };

    std::cout << "----- shared mutex test ------" << std::endl;
    std::list<std::shared_ptr<std::thread>> threadlist;
    {
        timers timer;

        for (int i = 0; i < READ_THREAD_COUNT; i++)
        {
            threadlist.push_back(std::make_shared<std::thread>(reader));
        }
        std::shared_ptr<std::thread> pw = std::make_shared<std::thread>(writer);

        for (auto &it : threadlist)
        {
            it->join();
        }
        pw->join();
    }
    std::cout <<"count:"<< counter.get() << ", temp:" << temp << std::endl;
}

void test_mutex()
{
    mutex_counter counter;
    unsigned int temp;

    auto writer = [&counter]() {
        for (unsigned int i = 0; i < LOOP_COUNT; i++) {
            counter.increment();
        }
    };

    auto reader = [&counter, &temp]() {
        for (unsigned int i = 0; i < LOOP_COUNT; i++) {
            temp = counter.get();
        }
    };

    std::cout << "----- mutex test ------" << std::endl;
    std::list<std::shared_ptr<std::thread>> threadlist;
    {
        timers timer;

        for (int i = 0; i < READ_THREAD_COUNT; i++)
        {
            threadlist.push_back(std::make_shared<std::thread>(reader));
        }

        std::shared_ptr<std::thread> pw = std::make_shared<std::thread>(writer);

        for (auto &it : threadlist)
        {
            it->join();
        }
        pw->join();
    }
    std::cout << "count:" << counter.get() << ", temp:" << temp << std::endl;
}



int main()
{
    test_shared_mutex();
    test_mutex();
    return 0;
}

//output
----- shared mutex test ------
Time-consuming:4309.85
count:5000000, temp:5000000
----- mutex test ------
Time-consuming:10541.4
count:5000000, temp:4953412

性能提升效果明显

参考://https://www.iteye.com/blog/aigo-2296462

作者:JasonLiThirty
链接:https://www.jianshu.com/p/86abf93a05e7/
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

发表回复

您的电子邮箱地址不会被公开。