通知图标

欢迎访问津桥芝士站

mutex:std::shared_mutex::lock_shared

来自AI助手的总结
C++17的std::shared_mutex允许多个线程共享访问资源,提高并发性能,同时确保写操作期间的安全性,适合读多写少的场景。

引入

随着多线程编程越来越受到开发者的青睐,C++标准库中的 <mutex> 头文件提供了许多工具以支持安全的并发编程。C++17 引入的 std::shared_mutex 是一种进阶的互斥量,它允许多个线程可以同时以共享方式访问同一个资源,但又确保在读操作时,如果有线程执行写操作,则不能读取。std::shared_mutex::lock_shared 方法专门用于申请共享锁,允许多个线程同时读取,而不干扰其它线程的读操作。正确理解并使用这一方法,对于设计高效的并发程序至关重要。

1. 特性与函数介绍

1.1 特性

  • 共享访问lock_shared() 方法支持多个线程并发读取共享资源,而不需要获取独占锁。这有助于在读多写少的场景中提高并行性能。
  • 线程安全:在写入操作未完成的情况下,无法进行读取操作,确保了对共享资源的安全性和一致性。
  • 灵活性:适用于复杂的多线程应用,同时支持区别读写访问,提高了代码的灵活性。

1.2 函数语法

std::shared_mutex::lock_shared 的基本语法如下:

#include <mutex>

class shared_mutex : public mutex {
public:
    void lock_shared(); // 申请共享锁
    ...
};
  • 无参数:此函数的调用不需要任何参数。
  • 无返回值:成功获取共享锁后不会返回任何值。

2. 完整示例代码

以下示例展示了如何使用 std::shared_mutex::lock_shared 在多线程环境中安全地进行读取操作。

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

std::shared_mutex smtx;           // 定义共享互斥锁
std::vector<int> sharedData;      // 共享数据区域

// 读取数据的函数
void readData() {
    smtx.lock_shared();  // 申请共享锁
    std::cout << "Thread " << std::this_thread::get_id() 
              << " read values: ";
    for (const auto& val : sharedData) {
        std::cout << val << " ";  // 输出共享数据
    }
    std::cout << std::endl;
    smtx.unlock_shared(); // 释放共享锁
}

// 写入数据的函数
void writeData(int value) {
    smtx.lock(); // 申请独占锁
    sharedData.push_back(value); 
    std::cout << "Thread " << std::this_thread::get_id() 
              << " wrote value: " << value << std::endl;
    smtx.unlock(); // 释放独占锁
}

int main() {
    const int numWriters = 3; // 写线程数量
    const int numReaders = 2;  // 读线程数量
    std::thread writers[numWriters];
    std::thread readers[numReaders];

    // 启动写线程
    for (int i = 0; i < numWriters; ++i) {
        writers[i] = std::thread(writeData, i + 1);
    }

    // 启动读线程
    for (int i = 0; i < numReaders; ++i) {
        readers[i] = std::thread(readData);
    }

    // 等待所有线程完成
    for (auto& writer : writers) {
        writer.join();
    }
    for (auto& reader : readers) {
        reader.join();
    }

    return 0;
}

3. 代码解析

  1. 引入必要的头文件

    • 本示例引入 <mutex><thread><shared_mutex> 和 <vector> 等头文件,以支持互斥量和线程操作,以及数据结构。
  2. 定义共享数据和互斥锁

    • 创建 std::shared_mutex smtx:供多个线程一起使用,以及一个 sharedData 向量作为共享数据的容器。
  3. 定义读取函数

    • readData 函数通过 smtx.lock_shared() 申请共享锁,允许多个线程同时读取共享数据;读取后,使用 smtx.unlock_shared() 释放共享锁。
  4. 定义写入函数

    • writeData 函数通过 smtx.lock() 申请独占锁来进行写入,并如法提供安全的数据操作,最后释放锁。
  5. 主函数/thread管理

    • 在 main 函数中,创建写线程和读线程,顺序启动并使用 join() 等待所有子线程执行结束。

4. 适用场景分析

4.1 读多写少的场景

在大量读取操作且较少写入的应用中,使用 std::shared_mutex::lock_shared 能带来较高的并发性能,例如日志记录、浏览状态信息等。

4.2 数据分享与统计系统

例如历史记录表现的系统允许同时向用户展示程序指标,lock_shared 能确保多个读取者无阻塞并获得实时数据。

4.3 服务访问控制

在网络应用或数据库的多个读操作请求时,一般需要保持数据一致,使用共享锁实现并行访问保证性能。

5. 总结

std::shared_mutex::lock_shared 提供了一种强大的工具,简化了跨线程访问共享数据的权限控制。通过允许多个线程并行读取,而在写入时保持对资源的独占性,它极大地提升了高并发环境下程序的效率和响应能力。合理使用 std::shared_mutex 将推动开发者在复杂的多线程场景中设计出更高效的系统。掌握这一机制不仅能够避免潜在的数据冲突,还能保证读取的数据一致性,为实现多线程程序提供更加稳固和优质的基础。

请登录后发表评论

    没有回复内容

正在唤醒异次元光景……