C++17里面的读写锁(shared_lock读锁,unique_lock写锁)
C++标准库本身没有直接提供读写锁,但C++11引入了一些工具,例如std::shared_mutex
(C++14引入的,C++17之前的标准库中可能不支持)以及相关的读锁定(std::shared_lock
)和写锁定(std::unique_lock
)机制,用于实现读写锁的功能。
下面是一个简单的示例,演示如何使用std::shared_mutex
实现读写锁:
文件名称是 test_rw_lock.cpp
在C++17下面编译的代码。
编译命令:
g++ test_rw_lock.cpp --std=c++17 -o wr.bin -l pthread
这里我们创建了10个写的线程,来执行fun1里面的方法,给iCount做自增操作。
我们创建了10个读的线程,来执行fun2里面读取的方法,输出iCount里面的值。
验证写锁:(写锁要能够解决写冲突)
1.不加锁,打印程序执行结果,预期结果是1000*10;多次执行程序,发现结果不是预期的值。
2.加读锁,打印程序执行结果,预期结果是1000*10;多次执行程序,发现结果不是预期的值。
3.加写锁(注释读锁),打印程序执行结果,预期结果是1000*10;多次执行程序,发现结果满足预期的值。
因此可以验证,写锁是成功的。
写锁避免了多线程写的冲突。
验证读锁:(验证多次读取功能,多次加读锁功能)
1.加读锁,打印程序结果,在日志里面看结果。如果有现成读取数值相同,说明读锁是正常的。(读锁要支持多次读取)
执行程序的时候,可以执行下面的命令,把数据导出到 文本里面。
我们如果在日志里面看到的fun2里面输出了同样的数值,说明2个线程都读取到了同一个数值,说明加多个读锁是没有冲突,没有问题的。说明读锁成功。
(wr.bin是我们编译生成的文件,“>”操作符是导出数据到文本。)
./wr.bin > a1.log
这个读写锁,在C++17的标准款中才开始支持。使用这里的读写锁,需要升级gcc版本。
这里有一个自己写的读写锁功能。移植了tars里面的读写锁代码。他不需要C++17标准款。
对于版本较低的gcc,可以考虑这里的代码。地址:https://github.com/liangzai90/henry-util
#include <iostream> #include <mutex> #include <shared_mutex> #include <thread> #include <vector> std::shared_mutex m_mutex; int iCount = 0; // test write lock void fun1() { for(int i=0;i<1000;++i) { //std::shared_lock<std::shared_mutex> lock(m_mutex); //read lock std::unique_lock<std::shared_mutex> lock(m_mutex); //write lock ++iCount; } } // test read lock void fun2(){ for(int i=0;i<1000;++i) { std::shared_lock<std::shared_mutex> lock(m_mutex); //read lock std::cout<<"read val is:"<< iCount << std::endl; } } int main() { //当你想要将线程放入std::vector容器时,你需要使用指向线程的指针或std::thread的移动语义, //因为std::thread对象不能被拷贝。 //std::vector<std::thread> vec_ths; //std::thread threads[10]; // 是使用数组方式创建一个包含10个std::thread对象的数组。 //这个数组用于存储线程对象,每个元素代表一个线程 constexpr size_t numThreads = 10; std::thread ths[numThreads]; std::thread r_ths[numThreads]; for(int i=0;i<numThreads;++i) { ths[i] = std::thread(fun1); r_ths[i] = std::thread(fun2); } for(int i=0;i<numThreads;++i) { ths[i].join(); // test write lock r_ths[i].join(); // test read lock. } std::this_thread::sleep_for(std::chrono::milliseconds(6666)); std::cout<<std::endl<<"finished iCount:"<<iCount<<std::endl; // g++ test_rw_lock.cpp --std=c++17 -o wr.bin -l pthread return 0; }