面试题答案
一键面试Mutex(互斥锁)
- 适用场景:Mutex 提供了独占访问的机制。无论是读取还是修改共享数据结构,线程都必须先获取 Mutex 的锁。这确保了同一时间只有一个线程能够访问共享数据,从而避免数据竞争。对于需要修改共享数据的线程,Mutex 是必不可少的,因为它能保证数据的一致性。对于只读取数据的线程,虽然可以使用 Mutex,但从性能角度看,它并非最优选择,因为每次读取都要独占锁,这可能会导致其他读取线程等待。
- 可能出现的问题:
- 死锁:如果多个线程以不同顺序获取多个 Mutex 锁,可能会导致死锁。例如,线程 A 获取了 Mutex1 并尝试获取 Mutex2,而线程 B 获取了 Mutex2 并尝试获取 Mutex1,此时两个线程都会无限期等待对方释放锁。
- 性能瓶颈:由于同一时间只有一个线程能持有锁,在高并发读取场景下,可能会因为频繁的锁竞争导致性能下降。
RwLock(读写锁)
- 适用场景:RwLock 区分了读操作和写操作。多个线程可以同时获取读锁来读取共享数据结构,因为读操作不会修改数据,所以不会产生数据竞争。而当有线程需要修改数据时,必须获取写锁,此时其他线程无论是读还是写都不能再获取锁。这使得 RwLock 在读写操作比例不均衡的场景下,尤其是读多写少的场景,能显著提高性能。例如,在一个数据库缓存系统中,大量线程可能只是读取缓存数据,而只有少数线程会更新缓存,这种情况下 RwLock 就非常适用。
- 可能出现的问题:
- 写饥饿:如果读操作非常频繁,写操作可能会一直无法获取写锁,导致写操作饥饿。因为只要有一个读锁被持有,写锁就无法获取。
- 复杂度增加:相较于 Mutex 简单的独占锁机制,RwLock 的读写锁机制在代码逻辑上更复杂,需要更仔细地处理读锁和写锁的获取与释放,以避免逻辑错误。