2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > C++多线程快速入门(四)shared_mutex以及读写锁应用

C++多线程快速入门(四)shared_mutex以及读写锁应用

时间:2021-01-04 21:25:09

相关推荐

C++多线程快速入门(四)shared_mutex以及读写锁应用

在前面的三讲中我们使用的mutex都是普通的std::mutex,这里介绍一下shared_mutex,版本为C++17

std::shared_mutex的底层实现时操作系统提供的读写锁,在读多写少的情况下,该shared_mutexmutex更加高效。

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

lockunlock分别用于获取写锁和解除写锁

lock_sharedunlock_shared分别用于获取读锁和解除读锁

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

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

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

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

当然在第二讲中,我们也谈到了unique_lock对于普通锁mutex的一种应用,当时是和std::lock_guard对比的。

下面是案例代码,对于共享资源我们创建多个读线程和一个写线程,分别使用std::mutexstd::shared_mutex做一下性能测试。

#include <iostream>#include <thread>#include <mutex>#include <shared_mutex>// 读线程数量#define READER_THREAD_COUNT 4// 最大循环次数#define LOOP_COUNT 500000class shared_mutex_counter {// 这里使用的锁是 shared_mutexprivate: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_lockstd::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_mutexprivate: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_mutexvoid 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);// 等待joinfor (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;}// 测试 mutexvoid 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);// 等待joinfor (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 mutexthread count 8spend time 1312result : 500000temp : 500000test shared_mutexthread count 8spend time 601result : 500000temp : 475766

有个问题,我同样程序在windows的clion和vs上跑结果差异较大,clion跑出来的结果shared_mutex耗时比mutex多好多。

linux下的vscode跑出来结果正常。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。