面试题答案
一键面试设计思路
- 互斥锁(Mutex):用于保护共享缓冲区,确保在同一时间只有一个线程可以访问共享缓冲区,防止多个线程同时读写造成的数据不一致。
- 信号量(Semaphore):
- 一个信号量(例如
empty
)用于表示共享缓冲区中的空闲空间,初始值为缓冲区的容量。当线程A要写入数据时,先获取empty
信号量,如果有空闲空间则可以写入,写入后释放表示有数据的信号量(例如full
)。 - 另一个信号量(例如
full
)用于表示共享缓冲区中的数据数量,初始值为0。当线程B要读取数据时,先获取full
信号量,如果有数据则可以读取,读取后释放empty
信号量。
- 一个信号量(例如
关键代码片段(以C++为例,使用C++11的线程库和信号量、互斥锁相关类)
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <chrono>
std::mutex mtx;
std::condition_variable empty, full;
std::queue<int> sharedBuffer;
const int bufferSize = 5;
void threadA() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
empty.wait(lock, [] { return sharedBuffer.size() < bufferSize; });
sharedBuffer.push(i);
std::cout << "Thread A pushed: " << i << std::endl;
lock.unlock();
full.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void threadB() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
full.wait(lock, [] { return!sharedBuffer.empty(); });
int data = sharedBuffer.front();
sharedBuffer.pop();
std::cout << "Thread B popped: " << data << std::endl;
lock.unlock();
empty.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main() {
std::thread a(threadA);
std::thread b(threadB);
a.join();
b.join();
return 0;
}
在上述代码中:
std::mutex mtx
是互斥锁,用于保护共享缓冲区sharedBuffer
。std::condition_variable empty
和std::condition_variable full
模拟信号量的功能,empty
表示缓冲区的空闲空间,full
表示缓冲区中的数据。threadA
线程向共享缓冲区写入数据,threadB
线程从共享缓冲区读取数据,通过互斥锁和条件变量(模拟信号量)保证了数据的正确读写,避免了竞态条件。