MST

星途 面试题库

面试题:C++中全局变量与局部变量在多线程环境下的内存问题

在多线程的C++程序中,全局变量和局部变量可能会面临哪些内存相关的问题?比如内存竞争、数据一致性等方面。如何通过编程手段(如使用特定的同步机制等)来解决这些问题,请举例说明。
44.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

全局变量在多线程中内存相关问题

  1. 内存竞争:多个线程同时读写全局变量时,可能导致数据不一致。例如,一个线程读取全局变量 count 的值,另一个线程同时对 count 进行修改,可能使第一个线程读取到旧值或不一致的值。
  2. 数据一致性:由于缓存一致性问题,不同线程对全局变量的修改可能不会立即对其他线程可见,导致数据不一致。例如,线程A修改了全局变量 data,但线程B由于缓存未更新,仍然读取到旧的 data 值。

局部变量在多线程中内存相关问题

  1. 内存竞争:局部变量一般每个线程都有自己的栈空间,所以本身不存在内存竞争问题。但如果局部变量是指向堆内存的指针,多个线程通过该指针访问堆内存时,可能产生内存竞争。例如,两个线程都通过同一个局部指针变量 ptr 访问堆上的同一块内存区域。
  2. 数据一致性:同样,对于局部变量本身,不存在数据一致性问题。但如果局部变量指向共享资源,如共享内存区域,也可能出现数据一致性问题,与全局变量类似。

解决方法及示例

  1. 互斥锁(std::mutex
    • 原理:互斥锁用于保护共享资源,同一时间只有一个线程能获取锁并访问共享资源。
    • 示例
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int globalCount = 0;

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

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

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

    std::cout << "Final globalCount: " << globalCount << std::endl;
    return 0;
}
  1. 读写锁(std::shared_mutex
    • 原理:允许多个线程同时读共享资源,但只允许一个线程写。写操作时需要独占锁,读操作可以共享锁。
    • 示例
#include <iostream>
#include <thread>
#include <shared_mutex>

std::shared_mutex sharedMtx;
int sharedData = 0;

void read() {
    sharedMtx.lock_shared();
    std::cout << "Read data: " << sharedData << std::endl;
    sharedMtx.unlock_shared();
}

void write() {
    sharedMtx.lock();
    ++sharedData;
    std::cout << "Write data: " << sharedData << std::endl;
    sharedMtx.unlock();
}

int main() {
    std::thread t1(read);
    std::thread t2(write);
    std::thread t3(read);

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

    return 0;
}
  1. 条件变量(std::condition_variable
    • 原理:用于线程间的同步,一个线程等待某个条件满足,另一个线程满足条件后通知等待的线程。
    • 示例
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    while (!ready) cv.wait(lock);
    std::cout << "thread " << id << '\n';
}

void go() {
    std::unique_lock<std::mutex> lock(mtx);
    ready = true;
    cv.notify_all();
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i)
        threads[i] = std::thread(print_id, i);

    std::cout << "10 threads ready to race...\n";
    go();

    for (auto& th : threads) th.join();

    return 0;
}