面试题答案
一键面试Mutex锁的公平性机制
在Go语言中,sync.Mutex
默认是非公平的。公平性指的是锁的获取顺序是否遵循请求顺序。
- 公平锁:当设置为公平锁(Go语言中没有直接设置公平性的方法,但通过一些方式可以模拟)时,等待时间最长的goroutine会优先获取锁。这意味着锁的授予是按照请求顺序进行的,类似于队列,先来先服务。
- 非公平锁:
sync.Mutex
默认是非公平的。在非公平锁的情况下,当锁被释放时,新到达的goroutine有机会在等待队列中的goroutine之前获取锁。这是因为非公平锁在释放锁后,会首先尝试让新请求的goroutine获取锁,如果获取失败才会从等待队列中唤醒一个goroutine。
公平性设置为true或false对程序性能的影响
- 公平锁(true)
- 优点:避免了goroutine饥饿问题,所有等待的goroutine都有机会按顺序获取锁,适用于对公平性要求较高的场景,比如资源分配场景,确保每个请求都能被公平对待。
- 缺点:性能相对较低。因为公平锁需要维护一个等待队列,每次锁的获取和释放都需要对队列进行操作,增加了额外的开销。而且由于新请求的goroutine不能立即获取锁,可能会导致CPU利用率降低。
- 场景举例:假设有多个goroutine需要访问共享的数据库连接池资源。如果使用公平锁,每个goroutine都能按照请求顺序获取连接,不会出现某个goroutine长时间获取不到连接的情况。但由于公平锁的队列操作开销,在高并发场景下,整体的数据库操作吞吐量可能会降低。
- 非公平锁(false)
- 优点:性能较高。由于新请求的goroutine有机会在等待队列中的goroutine之前获取锁,减少了上下文切换和队列操作的开销,提高了CPU利用率,在高并发场景下能获得更好的吞吐量。
- 缺点:可能会导致某些goroutine饥饿,即长时间无法获取锁。因为新请求的goroutine可能会不断抢占等待队列中goroutine的锁获取机会。
- 场景举例:在一个Web服务器中处理大量短时间的HTTP请求。使用非公平锁,新到达的请求有机会快速获取锁并处理,提高了整体的请求处理速度。但如果有一些处理时间较长的请求,可能会导致其他请求长时间等待,出现饥饿现象。