MST

星途 面试题库

面试题:C++指向常变量指针在多线程环境下数据传递的考量

在多线程编程环境中,使用指向常变量的指针进行数据传递。假设存在一个共享的复杂数据对象(例如一个包含多个成员变量和成员函数的类对象),一个线程负责更新这个对象的数据,而其他多个线程需要读取这些数据。请详细阐述如何使用指向常变量的指针来确保数据在传递和读取过程中的线程安全性,包括可能涉及到的同步机制(如互斥锁、读写锁等)的运用。给出一个代码框架示例,包含线程函数的定义、数据对象的声明以及指针传递的相关代码片段,并对关键部分进行详细注释。
47.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 确保线程安全的方法

  1. 使用互斥锁:在更新数据的线程中,获取互斥锁后进行数据更新操作,完成后释放互斥锁。在读取数据的线程中,获取互斥锁后通过指向常变量的指针读取数据,读完后释放互斥锁。
  2. 使用读写锁:更新数据的线程获取写锁进行数据更新,其他读取数据的线程获取读锁进行数据读取。读写锁允许多个线程同时读数据,但在写数据时会阻止其他线程读或写。

2. 代码框架示例

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

// 定义复杂数据对象类
class ComplexData {
public:
    int data1;
    double data2;
    // 其他成员变量和成员函数

    ComplexData() : data1(0), data2(0.0) {}
};

// 互斥锁用于保护数据对象
std::mutex dataMutex;
// 读写锁用于保护数据对象
std::shared_mutex rwMutex;

// 数据更新线程函数
void updateData(ComplexData* data) {
    // 使用互斥锁
    // std::lock_guard<std::mutex> lock(dataMutex);
    // 使用读写锁
    std::unique_lock<std::shared_mutex> lock(rwMutex);

    // 模拟数据更新操作
    data->data1++;
    data->data2 += 1.0;
}

// 数据读取线程函数
void readData(const ComplexData* data) {
    // 使用互斥锁
    // std::lock_guard<std::mutex> lock(dataMutex);
    // 使用读写锁
    std::shared_lock<std::shared_mutex> lock(rwMutex);

    // 读取数据
    std::cout << "Data1: " << data->data1 << ", Data2: " << data->data2 << std::endl;
}

int main() {
    ComplexData data;
    const ComplexData* constPtr = &data;

    // 创建更新数据的线程
    std::thread updateThread(updateData, &data);

    // 创建多个读取数据的线程
    std::thread readThreads[5];
    for (int i = 0; i < 5; ++i) {
        readThreads[i] = std::thread(readData, constPtr);
    }

    // 等待更新线程完成
    updateThread.join();

    // 等待所有读取线程完成
    for (auto& thread : readThreads) {
        thread.join();
    }

    return 0;
}

3. 关键部分注释

  1. 互斥锁相关
    • std::mutex dataMutex;:声明一个互斥锁 dataMutex,用于保护共享数据对象 ComplexData
    • std::lock_guard<std::mutex> lock(dataMutex);:在 updateDatareadData 函数中,使用 lock_guard 自动管理互斥锁的获取和释放。在构造 lock_guard 时获取互斥锁,在其析构时释放互斥锁。
  2. 读写锁相关
    • std::shared_mutex rwMutex;:声明一个读写锁 rwMutex,用于更细粒度地控制对共享数据对象的访问。
    • std::unique_lock<std::shared_mutex> lock(rwMutex);:在 updateData 函数中,使用 unique_lock 获取写锁,因为写操作需要独占访问权。
    • std::shared_lock<std::shared_mutex> lock(rwMutex);:在 readData 函数中,使用 shared_lock 获取读锁,允许多个线程同时读取数据。
  3. 线程函数
    • updateData 函数:负责更新共享数据对象,获取锁后进行数据更新操作。
    • readData 函数:负责读取共享数据对象,获取锁后通过指向常变量的指针读取数据,确保数据在读取过程中不会被修改。
  4. 主函数
    • 创建了一个 ComplexData 对象 data,并使用指向常变量的指针 constPtr 指向它。
    • 创建了一个更新数据的线程 updateThread 和五个读取数据的线程 readThreads
    • 等待更新线程和所有读取线程完成后,程序结束。