面试题答案
一键面试适用场景
- 读锁(RLock)适用场景:
- 当有多个 goroutine 同时进行读取操作而不会修改共享资源时,适合使用读锁。例如,多个 goroutine 同时读取一个配置文件的内容,由于读取操作不会改变配置内容,所以可以并发读取,提高效率。这种情况下使用读锁可以允许多个读操作同时进行,不会造成阻塞。
- 写锁(Lock)适用场景:
- 当 goroutine 需要对共享资源进行写入操作时,必须使用写锁。因为写入操作会改变共享资源的状态,如果多个写操作并发进行或者写操作与读操作并发进行,可能会导致数据不一致。例如,对数据库中的某条记录进行更新时,就需要使用写锁来保证操作的原子性,避免其他 goroutine 在写入过程中读取到不一致的数据。
区别
- 并发访问:
- 读锁(RLock):允许多个 goroutine 同时获取读锁并进行读取操作,即支持并发读。这是因为读操作不会改变共享资源的状态,多个读操作之间不会相互影响。
- 写锁(Lock):只允许一个 goroutine 获取写锁进行写入操作,在写锁被持有期间,其他任何 goroutine(无论是读操作还是写操作)都不能获取锁,会被阻塞,直到写锁被释放。
- 锁的互斥性:
- 读锁(RLock):读锁之间不互斥,多个读锁可以同时存在。但是读锁与写锁是互斥的,即当有一个写锁被持有时,其他 goroutine 不能获取读锁;同样,当有读锁被持有时,其他 goroutine 不能获取写锁。
- 写锁(Lock):写锁与读锁以及其他写锁都互斥。这是为了保证在写入共享资源时,不会有其他操作干扰,确保数据的一致性。
- 饥饿问题:
- 读锁(RLock):如果有大量的读操作持续进行,可能会导致写操作长时间等待,即写操作饥饿。因为读锁可以并发获取,当读操作频繁时,写锁很难有机会被获取。
- 写锁(Lock):由于写锁独占资源,当写操作频繁时,读操作也会被阻塞等待,不过相比读锁导致写操作饥饿,写锁导致读操作饥饿的情况相对较少,因为一般写操作完成时间相对较短。