首页 > 编程语言 >c++中的读写锁

c++中的读写锁

时间:2024-10-06 18:22:32浏览次数:9  
标签:线程 lock 读写 c++ mutex shared unique data

读写锁是一种特殊的锁机制,允许多个线程同时读取共享数据,但在写入共享数据时,只有一个线程可以进行写操作,其他线程必须等待。

这种机制对于读多写少的场景非常有效,可以提高并发性能。以下是通过 shared_lockunique_lockshared_mutexmutex 的解释来说明读写锁的实现和应用。

1. 基本概念

  • 读锁(Shared Lock)

    • 使用 shared_lock 加锁,允许多个线程同时持有读锁,这样它们可以并发地读取共享数据。
    • 在持有读锁的情况下,其他线程仍然可以获取读锁,但无法获取写锁。
  • 写锁(Exclusive Lock)

    • 使用 unique_lock 加锁,只有一个线程可以持有写锁。持有写锁的线程在写入数据时,其他线程无法获取任何类型的锁(无论是读锁还是写锁)。
    • 写锁的目的在于保证数据的安全性和一致性。

2. shared_mutexmutex

  • shared_mutex

    • 是 C++14 引入的一个互斥体类型,专门用于支持读写锁
      -** 它支持共享锁(通过 shared_lock)和独占锁(通过 unique_lock)**。通过这种方式,多个线程可以安全地读取数据,而在写入数据时,可以保证只有一个线程在写。
  • mutex

    • 是最基本的互斥体,提供了互斥访问共享资源的功能。
    • 使用 mutex 时,如果一个线程持有锁,其他线程都无法访问受保护的资源。

3. 示例代码

以下是一个示例,展示了如何使用 shared_mutexshared_lockunique_lock 实现一个简单的读写锁:

#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>
#include <chrono>

class SharedData {
private:
    int data;
    mutable std::shared_mutex mutex;

public:
    SharedData() : data(0) {}

    // 读操作
    int read() const {
        std::shared_lock<std::shared_mutex> lock(mutex); // 共享锁
        return data;
    }

    // 写操作
    void write(int value) {
        std::unique_lock<std::shared_mutex> lock(mutex); // 独占锁
        data = value;
    }
};

// 读线程函数
void reader(SharedData& shared_data, int id) {
    for (int i = 0; i < 5; ++i) {
        std::cout << "Reader " << id << " reads: " << shared_data.read() << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

// 写线程函数
void writer(SharedData& shared_data, int value) {
    for (int i = 0; i < 5; ++i) {
        shared_data.write(value);
        std::cout << "Writer writes: " << value << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
        value++; // 增加写入值
    }
}

int main() {
    SharedData shared_data;

    // 创建读线程
    std::vector<std::thread> readers;
    for (int i = 0; i < 3; ++i) {
        readers.emplace_back(reader, std::ref(shared_data), i);
    }

    // 创建写线程
    std::thread writer_thread(writer, std::ref(shared_data), 0);

    // 等待线程完成
    for (auto& r : readers) {
        r.join();
    }
    writer_thread.join();

    return 0;
}

4. 解释

  • 共享读取

    • read 方法中,使用 shared_lock 来加锁。这允许多个线程同时读取 data,因为它们不会阻塞彼此。
  • 独占写入

    • write 方法中,使用 unique_lock 来加锁。这保证了在写入数据时,其他线程不能读取或写入。
  • 线程安全

    • 通过使用 shared_mutex,确保在读取时允许并发访问,而在写入时则独占访问,有效提高了程序的并发性能。

总结

读写锁是提高读多写少场景下性能的有效机制。通过使用 shared_mutexshared_lockunique_lock,可以实现安全的并发访问,确保数据的一致性和正确性。这种方式在多线程编程中是非常常见的,特别是在需要频繁读取而写入相对较少的应用中。

标签:线程,lock,读写,c++,mutex,shared,unique,data
From: https://www.cnblogs.com/niumachen/p/18449263

相关文章

  • VC++ 6.0的安装及使用
    1.安装双击运行程序vc6_cn_full.exe进行安装如果需要更改安装目录,选择浏览进行安装地址的修改,否则点击下一步程序第一次启动会弹出提示框,可去掉“启动时显示提示”选项框,下一次就不会弹出该提示框    2. 一个简单的demo初学者建议选择“一个空程序”去创建控......
  • 搭建Redis“主-从-从”模式集群并使用 RedisTemplate 实现读写分离
    一、理论相关我们知道,Redis具有高可靠性,其含义包括:数据尽量少丢失-AOF和RDB服务尽量少中断-增加副本冗余量,将一份数据同时保存在多个实例上,即主从库模式Redis主从库模式-保证数据副本的一致(读写分离):读操作:主库、从库都可以接收写操作:首先到主库执行,然后,主库将写......
  • C++ explicit&noexcept关键字
    C++explicit&noexcept关键字explicit关键字在C++中,explicit关键字用于避免编译器在特定情况下进行隐式类型转换。它主要作用于构造函数和转换函数,防止不必要或意外的类型转换发生,从而提高代码的安全性和可读性。1.作用于构造函数当一个构造函数只接受一个参数时,它通常会......
  • c++ 键盘/鼠标交互
    c++键盘/鼠标交互鼠标操作点击加上如下宏定义#include<windows.h>#defineKEY_DOWN(VK_NONAME)((GetAsyncKeyState(VK_NONAME)&0x8000)?1:0)#defineKEY_UP(VK_NONAME)((GetAsyncKeyState(VK_NONAME)&0x8000)?0:1)如果获取左键的点击,可以使用如下的代码:KEY_D......
  • c++面经系列0:开篇-c++岗位面试都会问些什么?
    本文是C++岗位面试经验分享系列的开篇,敬请持续关注。在C++岗位面试中,通常首先进行技术面试,若通过则会进行HR面试。HR面试的内容先暂且略过,未来我们会有机会深入探讨,今天我们主要聚焦于技术面试的环节。技术面试通常由同岗位的同事或技术团队的领导担任面试官。在开场交流时,可以......
  • C++ 动态类型转换
    概念在C++中,dynamic_cast是一种运行时类型转换操作符。它主要用于在类的层次结构中进行安全的向下转换(将基类指针或引用转换为派生类指针或引用)。这种转换基于对象的实际类型进行检查,以确保转换的安全性。使用条件为了使用dynamic_cast,类层次结构中必须包含虚函数。这是因......
  • C++ 静态类型转换和动态类型转换的区别
    静态类型转换(static_cast)概念static_cast是C++中的一种类型转换操作符,用于在编译时进行类型转换。它主要用于具有明确的、编译器可以在编译阶段确定的类型转换关系的情况。这种转换通常在相关类型之间进行,例如基本数据类型之间的转换,或者在类层次结构中的向上转换(将派生类指......
  • C++ 重解释类型转换
    概念在C++中,reinterpret_cast被称为重新解释类型转换。它是一种强制类型转换操作符,用于将一种数据类型转换为另一种几乎完全不相关的数据类型。这种转换不进行任何数据的重新格式化或转换操作,只是简单地将数据的二进制表示重新解释为新的类型。语法语法形式为:reinterpret_......
  • C++ 常类型转换
    概念在C++中,常类型转换主要涉及到const_cast操作符,用于在特定情况下对const(常量)限定符进行处理。const关键字在C++中有重要意义,它表示被修饰的对象是常量,不能被修改。但在某些特殊情况下,需要在不破坏常量性语义的前提下,进行与常量相关的操作转换。const_cast的使用示例调......
  • C++ 类型强转
    static_cast基本概念static_cast主要用于在相关类型之间进行转换,这些类型之间存在某种隐式转换关系。它在编译时进行检查,是一种比较安全的类型转换方式。适用场景基本数据类型转换:例如将int转换为double,或者double转换为int(会截断小数部分)。intnumInt=5;doublenumD......