面试题答案
一键面试互斥锁(mutex)适用场景
- 共享资源访问:当多个线程需要访问共享资源(如共享内存、文件、数据库连接等)时,为防止数据竞争,使用互斥锁确保同一时间只有一个线程能访问该资源。
- 临界区保护:保护代码中的临界区,临界区是指访问共享资源的那段代码,互斥锁可以保证每次只有一个线程进入临界区执行代码。
线程同步原理
互斥锁有一个内部状态,用于表示锁的占用情况。在初始状态下,锁是未被占用的。当一个线程尝试获取(lock)互斥锁时,如果锁未被占用,该线程会成功获取锁并将其状态设为已占用,此时该线程可以进入临界区访问共享资源。当线程访问完共享资源后,会释放(unlock)互斥锁,将其状态重新设为未占用,以便其他线程可以获取锁进入临界区。如果一个线程尝试获取已被占用的互斥锁,该线程会被阻塞,直到持有锁的线程释放锁,这样就保证了同一时间只有一个线程能进入临界区,实现了线程同步。
代码实现
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
int num = 1;
void print_numbers(int id) {
while (num <= 10) {
mtx.lock();
if (num <= 10) {
std::cout << "Thread " << id << " prints " << num << std::endl;
num++;
}
mtx.unlock();
}
}
int main() {
std::thread t1(print_numbers, 1);
std::thread t2(print_numbers, 2);
t1.join();
t2.join();
return 0;
}
在这段代码中,定义了一个std::mutex
对象mtx
用于保护共享变量num
。两个线程t1
和t2
在函数print_numbers
中尝试获取互斥锁mtx
,获取成功后打印当前num
的值并递增num
,然后释放互斥锁,从而实现两个线程交替打印数字1 - 10。