zoukankan      html  css  js  c++  java
  • std::shared_mutex和std::mutex的性能对比(banchmark)

    原文作者:@玄冬Wong

    转载请注明原文出处:http://aigo.iteye.com/blog/2296462

    key world: std::shared_mutex、std::mutex、performance、benchmark、性能测试

    shared_mutex的适用场景比较特殊:一个或多个读线程同时读取共享资源,且只有一个写线程来修改这个资源,这种情况下才能从shared_mutex获取性能优势。

    cppreference文档

    http://en.cppreference.com/w/cpp/thread/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

    /************************************************************************/  
    /* std::shared_mutex与std::mutex的性能对比 */  
    /************************************************************************/  
      
    #pragma once  
      
    #define WRITE_THREAD_COUNT 8  
    #define LOOP_COUNT 5000000  
      
    #include <iostream>  
    #include <mutex>  // For std::unique_lock  
    #include <shared_mutex>  
    #include <thread>  
      
    class shared_mutex_counter {  
    public:  
        shared_mutex_counter() = default;  
      
        // Multiple threads/readers can read the counter's value at the same time.  
        unsigned int get() const {  
            std::shared_lock<std::shared_mutex> lock(mutex_);  
            return value_;  
        }  
      
        // Only one thread/writer can increment/write the counter's value.  
        void increment() {  
            std::unique_lock<std::shared_mutex> lock(mutex_);  
            value_++;  
        }  
      
        // Only one thread/writer can reset/write the counter's value.  
        void reset() {  
            std::unique_lock<std::shared_mutex> lock(mutex_);  
            value_ = 0;  
        }  
      
    private:  
        mutable std::shared_mutex mutex_;  
        unsigned int value_ = 0;  
    };  
      
    class mutex_counter {  
    public:  
        mutex_counter() = default;  
      
        unsigned int get() const {  
            std::unique_lock<std::mutex> lk(mutex_);  
            return value_;  
        }  
      
        void increment() {  
            std::unique_lock<std::mutex> lk(mutex_);  
            value_++;  
        }  
      
    private:  
        mutable std::mutex mutex_;  
        unsigned int value_ = 0;  
    };  
      
    void test_shared_mutex()  
    {  
        shared_mutex_counter counter;  
        int temp;  
      
        auto writer = [&counter]() {  
            for (int i = 0; i < LOOP_COUNT; i++) {  
                counter.increment();  
            }  
        };  
      
        auto reader = [&counter, &temp]() {  
            for (int i = 0; i < LOOP_COUNT; i++) {  
                temp = counter.get();  
            }  
        };  
      
        std::thread** tarray = new std::thread*[WRITE_THREAD_COUNT];  
      
        clock_t start = clock();  
      
        for (int i = 0; i < WRITE_THREAD_COUNT; i++)  
        {  
            tarray[i] = new std::thread(reader);  
        }  
      
        std::thread tw(writer);  
      
        for (int i = 0; i < WRITE_THREAD_COUNT; i++)  
        {  
            tarray[i]->join();  
        }  
        tw.join();  
      
        clock_t end = clock();  
        printf("[test_shared_mutex]
    ");  
        printf("thread count:%d
    ", WRITE_THREAD_COUNT);  
        printf("result:%d cost:%dms temp:%d 
    ", counter.get(), end - start, temp);  
    }  
      
      
    void test_mutex()  
    {  
        mutex_counter counter;  
      
        int temp;  
      
        auto writer = [&counter]() {  
            for (int i = 0; i < LOOP_COUNT; i++) {  
                counter.increment();  
            }  
        };  
      
        auto reader = [&counter, &temp]() {  
            for (int i = 0; i < LOOP_COUNT; i++) {  
                temp = counter.get();  
            }  
        };  
      
        std::thread** tarray = new std::thread*[WRITE_THREAD_COUNT];  
      
        clock_t start = clock();  
      
        for (int i = 0; i < WRITE_THREAD_COUNT; i++)  
        {  
            tarray[i] = new std::thread(reader);  
        }  
      
        std::thread tw(writer);  
      
        for (int i = 0; i < WRITE_THREAD_COUNT; i++)  
        {  
            tarray[i]->join();  
        }  
        tw.join();  
      
        clock_t end = clock();  
        printf("[test_mutex]
    ");  
        printf("thread count:%d
    ", WRITE_THREAD_COUNT);  
        printf("result:%d cost:%dms temp:%d 
    ", counter.get(), end - start, temp);  
    }  
      
    int main() {  
        //为了排除测试程序的无关因素,测试时只开启一个  
        //test_shared_mutex();  
        test_mutex();  
    }  

    测试结果:

    2线程抢占

    [test_mutex]

    thread count:2

    result:10000000 cost:1348ms temp:10000000

    [test_shared_mutex]

    thread count:2

    result:10000000 cost:699ms temp:10000000

    4线程抢占

    [test_mutex]

    thread count:4

    result:10000000 cost:2448ms temp:10000000

    [test_shared_mutex]

    thread count:4

    result:10000000 cost:1233ms temp:10000000

    8线程抢占

    [test_mutex]

    thread count:8

    result:5000000 cost:2452ms temp:5000000

    [test_shared_mutex]

    thread count:8

    result:5000000 cost:1123ms temp:3231860

    结论:

    在多个只读线程和一个写线程的情况下,shared_mutex比mutex快一倍。

    PS:std::shared_mutex和std::mutex分别对应java中的ReentrantReadWriteLockReentrantLock

  • 相关阅读:
    【本人译作推荐】Windows 8应用开发:C#和XAML卷(原名:Building Windows 8 Apps with C# and XAML)
    ODAC的安装以及Entity Framework for Oracle 基本配置
    ExtJs API 下载以及部署
    ArcGis(01)——地图切片以及发布底图服务
    ubuntu下安装Vmare Workstation,并安装mac补丁
    sencha app build 到 Capturing theme image不执行
    Ext Sencha Cmd 6 环境安装
    SqlServer CTE 递归查询 Oracle递归查询
    ibatis.net调用oracle存储过返回游标SYS_REFCURSOR结果集
    SpringMVC从入门到精通之第四章
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12046013.html
Copyright © 2011-2022 走看看