面试题答案
一键面试- 定义条件变量和互斥锁:
- 定义两个条件变量
cv1
和cv2
,分别用于任务 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;
- 定义两个条件变量
- 任务 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(); }
- 任务 A 执行完自己的工作后,通过
- 任务 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(); }
- 任务 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; }
- 处理竞争条件:
- 使用互斥锁
mutex
来保护共享资源(这里主要是条件变量的相关操作)。 - 在调用
cv1.wait(lock)
和cv2.wait(lock)
时,传递lock
以保证在等待过程中,互斥锁被释放,避免死锁,同时在等待结束后,互斥锁重新被获取,保护共享资源。
- 使用互斥锁
- 处理死锁问题:
- 确保在调用
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; }
- 确保在调用
通过以上设计,运用条件变量和互斥锁实现了多线程间复杂的同步机制,并有效处理了竞争条件和死锁问题。