MST

星途 面试题库

面试题:C++循环语句在多线程环境下的同步与并发控制

在多线程编程中,多个线程可能同时执行包含循环语句的代码段,例如多个线程同时对共享数据进行循环累加操作。请详细说明如何使用C++的多线程库(如std::thread、std::mutex、std::condition_variable等)来确保循环执行过程中的数据一致性和线程同步,避免竞态条件。编写一个完整的多线程程序示例,展示如何实现对共享资源的安全循环访问,同时分析该方案在高并发场景下的可扩展性和性能瓶颈。
27.0万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

确保数据一致性和线程同步的方法

  1. 互斥锁(std::mutex:用于保护共享资源,在访问共享资源前锁定互斥锁,访问结束后解锁。这样可以保证同一时间只有一个线程能访问共享资源,避免竞态条件。
  2. 条件变量(std::condition_variable:配合互斥锁使用,用于线程间的同步。当某个条件满足时,通知等待在条件变量上的线程。

多线程程序示例

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

std::mutex mtx;
std::condition_variable cv;
int shared_data = 0;
const int max_value = 100;

void increment_shared_data(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    while (shared_data < max_value) {
        shared_data++;
        std::cout << "Thread " << id << " incremented shared_data to " << shared_data << std::endl;
        cv.notify_all();
    }
}

int main() {
    const int num_threads = 5;
    std::vector<std::thread> threads;

    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back(increment_shared_data, i);
    }

    for (auto& thread : threads) {
        thread.join();
    }

    return 0;
}

可扩展性和性能瓶颈分析

  1. 可扩展性
    • 这种基于互斥锁和条件变量的方案在一定程度上具有可扩展性。随着线程数量的增加,仍然能够保证数据的一致性。
    • 然而,当线程数量非常多(例如数千个线程)时,由于锁竞争的加剧,性能会显著下降。
  2. 性能瓶颈
    • 锁竞争:互斥锁会导致线程间的锁竞争,当多个线程频繁竞争同一把锁时,会增加线程等待时间,降低整体性能。
    • 上下文切换:大量线程竞争锁会导致频繁的上下文切换,增加系统开销。
    • 缓存一致性:多线程访问共享数据可能导致缓存一致性问题,特别是在多核处理器上,缓存之间的数据同步会带来额外开销。