MST

星途 面试题库

面试题:C++中多线程引用全局变量时如何避免数据竞争

在C++编程中,假设有一个全局变量 `int globalVar = 0;`,现在有两个线程,一个线程对 `globalVar` 进行加1操作,另一个线程对 `globalVar` 进行减1操作。请描述如何使用C++的标准库来避免这两个线程操作 `globalVar` 时的数据竞争问题,并简单给出代码示例。
17.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

在C++中,可以使用<mutex>库来避免数据竞争问题。mutex(互斥锁)用于保护共享资源,确保同一时间只有一个线程可以访问该资源。

以下是代码示例:

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

std::mutex mtx;
int globalVar = 0;

void increment() {
    for (int i = 0; i < 10000; ++i) {
        mtx.lock();
        globalVar++;
        mtx.unlock();
    }
}

void decrement() {
    for (int i = 0; i < 10000; ++i) {
        mtx.lock();
        globalVar--;
        mtx.unlock();
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(decrement);

    t1.join();
    t2.join();

    std::cout << "Final value of globalVar: " << globalVar << std::endl;
    return 0;
}

在上述代码中:

  1. 定义了一个全局的std::mutex mtx对象。
  2. increment函数和decrement函数在对globalVar进行操作前,先调用mtx.lock()锁定互斥锁,操作完成后调用mtx.unlock()解锁互斥锁。这样就保证了同一时间只有一个线程可以修改globalVar,避免了数据竞争。
  3. main函数中创建并启动两个线程,分别执行incrementdecrement函数,最后等待两个线程执行完毕,并输出globalVar的最终值。

另外,也可以使用std::lock_guard来简化锁的管理,std::lock_guard在构造函数中自动锁定互斥锁,在析构函数中自动解锁互斥锁,修改后的代码如下:

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

std::mutex mtx;
int globalVar = 0;

void increment() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        globalVar++;
    }
}

void decrement() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        globalVar--;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(decrement);

    t1.join();
    t2.join();

    std::cout << "Final value of globalVar: " << globalVar << std::endl;
    return 0;
}

这种方式更简洁且安全,因为即使在函数执行过程中发生异常,std::lock_guard也能保证互斥锁被正确解锁。