1. 锁的基础概念
1.1 CAS与轮询
1.1.1 cas实现锁
在锁的实现中现在越来越多的采用CAS来进行,通过利用处理器的CAS指令来实现对给定变量的值交换来进行锁的获取
1.1.2 轮询锁
在多线程并发的情况下很有可能会有线程CAS失败,通常就会配合for循环采用轮询的方式去尝试重新获取锁
1.2 锁的公平性
锁从公平性上通常会分为公平锁和非公平锁,主要取决于在锁获取的过程中,先进行锁获取的线程是否比后续的线程更先获得锁,如果是则就是公平锁:多个线程按照获取锁的顺序依次获得锁,否则就是非公平性
1.3 饥饿与排队
1.3.1 锁饥饿
锁饥饿是指因为大量线程都同时进行获取锁,某些线程可能在锁的CAS过程中一直失败,从而长时间获取不到锁
1.3.2 排队机制
上面提到了CAS和轮询锁进行锁获取的方式,可以发现如果已经有线程获取了锁,但是在当前线程在多次轮询获取锁失败的时候,就没有必要再继续进行反复尝试浪费系统资源,通常就会采用一种排队机制,来进行排队等待
1.4 位计数
在大多数编程语言中针对实现基于CAS的锁的时候,通常都会采用一个32位的整数来进行锁状态的存储
2. mutex实现
2.1 成员变量与模式
2.1.1 成员变量
在go的mutex中核心成员变量只有两个state和sema,其通过state来进行锁的计数,而通过sema来实现排队
type Mutex struct {
state int32
sema uint32
}
2.1.2 锁模式
锁模式主要分为两种
描述 | 公平性 | |
---|---|---|
正常模式 | 正常模式下所有的goroutine按照FIFO的顺序进行锁获取,被唤醒的goroutine和新请求锁的goroutine同时进行锁获取,通常新请求锁的goroutine更容易获取锁 | 否 |
饥饿模式 | 饥饿模式所有尝试获取锁的goroutine进行等待排队,新请求锁的goroutine不会进行锁获取,而是加入队列尾部等待获取锁 | 是 |
上面可以看到其实在正常模式下,其实锁的性能是最高的如果多个goroutine进行锁获取后立马进行释放则可以避免多个线程