MST

星途 面试题库

面试题:C++全局变量在多线程环境下引用的注意事项

在一个多线程的C++程序中,存在一个全局变量 `std::vector<int> globalVec;`,多个线程会对这个全局变量进行读和写操作。请阐述在这种情况下,引用该全局变量可能会出现哪些问题,并说明如何通过合适的机制(如互斥锁、原子操作等)来保证全局变量引用的正确性和线程安全性,给出关键代码片段。
23.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

可能出现的问题

  1. 数据竞争(Data Race):多个线程同时读写 globalVec 时,可能会导致数据不一致。例如,一个线程正在写入数据,另一个线程同时读取,可能读取到不完整或错误的数据。
  2. 竞态条件(Race Condition):由于线程执行顺序的不确定性,可能会导致程序的行为出现不可预测的结果。例如,多个线程同时对 globalVec 进行插入操作,可能导致 globalVec 的元素顺序不符合预期。

解决方案

  1. 使用互斥锁(Mutex):互斥锁可以保证在同一时间只有一个线程能够访问 globalVec

关键代码片段:

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

std::vector<int> globalVec;
std::mutex globalVecMutex;

void writeToGlobalVec(int value) {
    std::lock_guard<std::mutex> lock(globalVecMutex);
    globalVec.push_back(value);
}

int readFromGlobalVec(int index) {
    std::lock_guard<std::mutex> lock(globalVecMutex);
    if (index < globalVec.size()) {
        return globalVec[index];
    }
    return -1; // 表示无效索引
}

int main() {
    std::thread writer1(writeToGlobalVec, 1);
    std::thread writer2(writeToGlobalVec, 2);
    std::thread reader1([&] { std::cout << "Read value: " << readFromGlobalVec(0) << std::endl; });

    writer1.join();
    writer2.join();
    reader1.join();

    return 0;
}
  1. 使用原子操作(Atomic Operations):虽然 std::vector 本身不是原子类型,但可以对其某些操作进行原子化处理。例如,使用原子计数器来记录 globalVec 的大小,以避免在读取和写入 globalVec 时出现竞争条件。

关键代码片段:

#include <iostream>
#include <vector>
#include <atomic>
#include <thread>

std::vector<int> globalVec;
std::atomic<int> globalVecSize(0);

void writeToGlobalVec(int value) {
    globalVec.push_back(value);
    globalVecSize++;
}

int readFromGlobalVec(int index) {
    if (index < globalVecSize.load()) {
        return globalVec[index];
    }
    return -1; // 表示无效索引
}

int main() {
    std::thread writer1(writeToGlobalVec, 1);
    std::thread writer2(writeToGlobalVec, 2);
    std::thread reader1([&] { std::cout << "Read value: " << readFromGlobalVec(0) << std::endl; });

    writer1.join();
    writer2.join();
    reader1.join();

    return 0;
}

这种方法虽然不能完全保证 globalVec 操作的原子性,但可以在一定程度上减少数据竞争的风险。对于复杂的 vector 操作,还是建议使用互斥锁来保证线程安全。