面试题答案
一键面试在多线程环境中使用控制结构可能遇到的问题
- 数据竞争:
- 解释:不同线程同时访问和修改共享数据时,如果没有适当的同步机制,可能会导致数据不一致。例如,在
if - else
语句中,一个线程可能在判断条件后,还未执行相应操作时,另一个线程修改了共享数据,导致第一个线程执行的操作基于过时的数据。在for
循环中,若循环变量是共享的,多个线程同时对其进行读写操作,也会产生数据竞争。 - 示例:假设有两个线程对一个共享变量
count
进行操作,一个线程在if (count > 0)
判断后,还未执行count--
时,另一个线程将count
减为 0,就会出现逻辑错误。
- 解释:不同线程同时访问和修改共享数据时,如果没有适当的同步机制,可能会导致数据不一致。例如,在
- 死锁:
- 解释:当两个或多个线程相互等待对方释放锁时,就会发生死锁。例如,线程 A 持有锁
mutexA
并尝试获取锁mutexB
,而线程 B 持有锁mutexB
并尝试获取锁mutexA
,双方都不会释放已持有的锁,从而陷入死锁。在使用for
循环进行复杂资源获取时,如果获取顺序不一致,很容易出现死锁情况。
- 解释:当两个或多个线程相互等待对方释放锁时,就会发生死锁。例如,线程 A 持有锁
使用同步机制解决问题
- mutex(互斥锁):
- 作用:用于保护共享资源,确保同一时间只有一个线程可以访问共享资源。
- 使用方法:在访问共享资源前,线程需要先获取
mutex
,访问完后释放mutex
。例如在if - else
或for
循环中涉及共享资源操作时,在进入相关代码块前加锁,离开时解锁。
- condition_variable(条件变量):
- 作用:用于线程间的同步,一个线程可以等待某个条件满足,而另一个线程在条件满足时通知等待的线程。常用于在
while
循环中,线程等待某个条件发生变化后再继续执行。 - 使用方法:通常与
mutex
配合使用。一个线程在while
循环中使用condition_variable
的wait
方法等待条件,另一个线程在条件满足时调用condition_variable
的notify_one
或notify_all
方法通知等待的线程。
- 作用:用于线程间的同步,一个线程可以等待某个条件满足,而另一个线程在条件满足时通知等待的线程。常用于在
多线程程序示例
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;
bool finished = false;
void producer(int id) {
for (int i = 0; i < 5; ++i) {
std::unique_lock<std::mutex> lock(mtx);
dataQueue.push(i * id);
std::cout << "Producer " << id << " produced: " << i * id << std::endl;
lock.unlock();
cv.notify_one();
}
std::unique_lock<std::mutex> lock(mtx);
finished = true;
cv.notify_all();
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return!dataQueue.empty() || finished; });
if (dataQueue.empty() && finished) {
break;
}
int data = dataQueue.front();
dataQueue.pop();
std::cout << "Consumer consumed: " << data << std::endl;
}
}
int main() {
std::thread producer1(producer, 1);
std::thread producer2(producer, 2);
std::thread consumerThread(consumer);
producer1.join();
producer2.join();
consumerThread.join();
return 0;
}
在这个示例中,producer
线程生产数据并放入共享队列 dataQueue
中,consumer
线程从队列中取出数据。mutex
用于保护共享队列,condition_variable
用于线程间的同步,确保消费者线程在队列有数据或生产结束时才进行消费操作,避免了数据竞争和死锁等问题。