C++17里面的读写锁(shared_lock读锁,unique_lock写锁)

发布时间 2023-12-29 18:28:42作者: He_LiangLiang

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 

 

 
#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;
}