GXB's Blog

  • 首页
  • 学习笔记
    • C++
    • golang
    • javascript
    • python
  • 工具分享
  • 其它
Kratos
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. 学习笔记
  3. C++
  4. 正文

C++多线程shared_mutex以及读写锁应用

2026年4月24日 1点热度 0人点赞 0条评论

在前面的三讲中我们使用的mutex都是普通的std::mutex,这里介绍一下shared_mutex,版本为C++17
std::shared_mutex的底层实现时操作系统 提供的读写锁,在读多写少的情况下,该shared_mutex比mutex更加高效。

它提供了常用的四种方法:

lock和unlock分别用于获取写锁和解除写锁

lock_shared和unlock_shared分别用于获取读锁和解除读锁

写锁模式称为排他锁,读锁模式称为共享锁。

c++11和c++14标准中分别引入unique_lock和shared_lock两个类模板配合shared_mutex使用。

对象在构造时自动对std::shared_mutex加锁,析构时自动对其解锁。

前者用于加解写锁,后者用于加解读锁。

当然在第二讲中,我们也谈到了unique_lock对于普通锁mutex的一种应用,当时是和std::lock_guard对比的。
下面是案例代码,对于共享资源我们创建多个读线程和一个写线程,分别使用std::mutex和std::shared_mutex做一下性能测试。

#include <iostream>
#include <thread>
#include <mutex>
#include <shared_mutex>


// 读线程数量
#define READER_THREAD_COUNT 4
// 最大循环次数
#define LOOP_COUNT 500000


class shared_mutex_counter {
// 这里使用的锁是 shared_mutex
private:
    mutable std::shared_mutex m_mutex;
    unsigned int m_value = 0;     // 多个线程共享的资源
public:
    shared_mutex_counter() = default;
    ~shared_mutex_counter() = default;

    // shared_lock  同一时可多个读线程可以同时访问m_value的值
    unsigned int get() const
    {
        // 这里使用shared_lock
        std::shared_lock<std::shared_mutex> lock(m_mutex);
        return m_value;
    }
    // unique_lock 同一时间仅有一个写线程可以修改m_value的值
    void incremet() {
        std::unique_lock<std::shared_mutex> lock(m_mutex);
        m_value++;
    }
};

class mutex_counter {
// 这里使用的锁是 shared_mutex
private:
    mutable std::mutex m_mutex;
    unsigned int m_value = 0;     // 多个线程共享的资源
public:
    mutex_counter() = default;
    ~mutex_counter() = default;

    // 同一时间仅有一个读线程可以同时访问m_value的值
    unsigned int get() const
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        return m_value;
    }
    // 同一时间仅有一个写线程可以修改m_value的值
    void incremet()
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_value++;
    }
};

// 测试 shared_mutex
void test_shared_mutex()
{
    shared_mutex_counter counter;
    unsigned int temp;

    // 写线程函数
    auto write = [&counter]() {
        for (int i = 0; i < LOOP_COUNT; i++) {
            counter.incremet();
        }
    };

    // 读线程函数
    auto read = [&counter, &temp]() {
        for (int i = 0; i < LOOP_COUNT; i++) {
            temp = counter.get();
        }
    };

    // 存放读线程对象指针的数组
    std::thread** tarray = new std::thread* [READER_THREAD_COUNT];

    // 记录起始时间
    clock_t start = clock();

    // 创建 READER_THREAD_COUNT 个读线程
    for (int i = 0; i < READER_THREAD_COUNT; i++) {
        tarray[i] = new std::thread(read);
    }

    // 创建一个写线程
    std::thread tw(write);
    // 等待join
    for (int i = 0; i < READER_THREAD_COUNT; i++) {
        tarray[i]->join();
    }
    tw.join();

    clock_t end = clock();
    std::cout << "test shared_mutex" << std::endl;
    std::cout << "thread count " << READER_THREAD_COUNT << std::endl;
    std::cout << "spend time " << end - start << std::endl;
    std::cout << "result : " << counter.get() << std::endl;
    std::cout << "temp : " << temp << std::endl;
}

// 测试 mutex
void test_mutex()
{
    mutex_counter counter;
    unsigned int temp;

    // 写线程函数
    auto write = [&counter]() {
        for (int i = 0; i < LOOP_COUNT; i++) {
            counter.incremet();
        }
    };

    // 读线程函数
    auto read = [&counter, &temp]() {
        for (int i = 0; i < LOOP_COUNT; i++) {
            temp = counter.get();
        }
    };

    // 存放读线程对象指针的数组
    std::thread** tarray = new std::thread* [READER_THREAD_COUNT];

    // 记录起始时间
    clock_t start = clock();

    // 创建 READER_THREAD_COUNT 个读线程
    for (int i = 0; i < READER_THREAD_COUNT; i++) {
        tarray[i] = new std::thread(read);
    }

    // 创建一个写线程
    std::thread tw(write);
    // 等待join
    for (int i = 0; i < READER_THREAD_COUNT; i++) {
        tarray[i]->join();
    }
    tw.join();

    clock_t end = clock();
    std::cout << "test mutex" << std::endl;
    std::cout << "thread count " << READER_THREAD_COUNT << std::endl;
    std::cout << "spend time " << end - start << std::endl;
    std::cout << "result : " << counter.get() << std::endl;
    std::cout << "temp : " << temp << std::endl;
}

int main() {
    test_mutex();
    std::cout << std::endl;
    test_shared_mutex();
    return 0;
}

测试结果如下:

test mutex
thread count 8
spend time 1312
result : 500000
temp : 500000

test shared_mutex
thread count 8
spend time 601
result : 500000
temp : 475766
标签: 暂无
最后更新:2026年4月24日

admin

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

归档

  • 2026 年 4 月

分类

  • C++
  • golang
  • 学习笔记
  • 工具分享

COPYRIGHT © 2026 GXB's Blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang