MST

星途 面试题库

面试题:并发与同步:条件变量在复杂多线程任务依赖场景下的运用

在一个多线程程序中,有多个任务线程(A、B、C、D),任务 A 完成后需要通知任务 B 和任务 C 开始执行,任务 B 和任务 C 都完成后再通知任务 D 开始执行。请详细阐述如何运用条件变量来设计这种复杂的线程同步机制,包括如何处理可能出现的竞争条件和死锁问题。
45.2万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试
  1. 定义条件变量和互斥锁
    • 定义两个条件变量 cv1cv2,分别用于任务 A 通知任务 B 和 C,以及任务 B 和 C 通知任务 D。
    • 定义一个互斥锁 mutex,用于保护共享资源和条件变量的相关操作。
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    std::mutex mutex;
    std::condition_variable cv1;
    std::condition_variable cv2;
    
  2. 任务 A 的实现
    • 任务 A 执行完自己的工作后,通过 cv1.notify_all() 通知任务 B 和 C。
    void taskA() {
        // 任务 A 的具体工作
        std::cout << "Task A is done." << std::endl;
        std::unique_lock<std::mutex> lock(mutex);
        cv1.notify_all();
    }
    
  3. 任务 B 和 C 的实现
    • 任务 B 和 C 在开始执行前,需要等待任务 A 的通知。
    • 当收到任务 A 的通知后,执行自己的工作。
    • 执行完工作后,通过 cv2.notify_one() 通知任务 D(只需要有一个线程通知即可)。
    void taskB() {
        std::unique_lock<std::mutex> lock(mutex);
        cv1.wait(lock);
        // 任务 B 的具体工作
        std::cout << "Task B is done." << std::endl;
        cv2.notify_one();
    }
    void taskC() {
        std::unique_lock<std::mutex> lock(mutex);
        cv1.wait(lock);
        // 任务 C 的具体工作
        std::cout << "Task C is done." << std::endl;
        cv2.notify_one();
    }
    
  4. 任务 D 的实现
    • 任务 D 在开始执行前,需要等待任务 B 和 C 的通知。
    void taskD() {
        std::unique_lock<std::mutex> lock(mutex);
        cv2.wait(lock);
        // 任务 D 的具体工作
        std::cout << "Task D is done." << std::endl;
    }
    
  5. 处理竞争条件
    • 使用互斥锁 mutex 来保护共享资源(这里主要是条件变量的相关操作)。
    • 在调用 cv1.wait(lock)cv2.wait(lock) 时,传递 lock 以保证在等待过程中,互斥锁被释放,避免死锁,同时在等待结束后,互斥锁重新被获取,保护共享资源。
  6. 处理死锁问题
    • 确保在调用 cv1.notify_all()cv2.notify_one() 之前,已经获取了相应的互斥锁 mutex,并且在通知之后,及时释放互斥锁。
    • 按照一定的顺序获取和释放锁,避免出现循环等待的情况。例如,所有线程都是先获取 mutex,再进行条件变量的相关操作。
    • main 函数中创建线程并启动:
    int main() {
        std::thread threadA(taskA);
        std::thread threadB(taskB);
        std::thread threadC(taskC);
        std::thread threadD(taskD);
        threadA.join();
        threadB.join();
        threadC.join();
        threadD.join();
        return 0;
    }
    

通过以上设计,运用条件变量和互斥锁实现了多线程间复杂的同步机制,并有效处理了竞争条件和死锁问题。