Go Mutex加锁流程笔记
Mutex是一种基于CAS的自旋锁
获取锁——步骤
-
(1)协程调用Lock()函数。
-
(2)判断这个锁是否未初始化,如果该锁没有初始化,则对该锁进行初始化设置,然后获取锁,Lock()函数返回。如果该锁已被初始化过,则进入下一步操作。
-
(3)判断锁与协程的当前状态,如果该锁处于加锁状态且当前协程不处于饥饿状态,则尝试获取该锁的协程会进入自旋状态(最多自旋4次)。
-
(4)自旋完成后,计算当前锁的状态,协程尝试获取锁,如果获取成功,Lock()函数返回。如果获取失败,则进入下一步操作。
-
(5)自旋完成后尝试获取锁失败,该协程进入休眠状态,协程进入阻塞状态,并不断尝试获取信号。
-
(6)休眠协程获取到信号(有其他协程释放了锁),被唤醒,此时go会判断当前协程是否处于饥饿状态(如果协程从调用Lock()函数起,超过1ms后都没有成功获取到锁,则该协程进入饥饿状态)。如果该协程处于饥饿状态,不会启动自旋过程,而是再次被阻塞,一旦有其他的协程释放了锁,那么该饥饿协程就会被唤醒并直接获取锁,Lock()函数返回。如果该协程处于正常状态,则进入下一步操作。
-
(7)如果协程被判定处于正常状态,即满足再次启动自旋条件(协程从调用Lock()函数起到现在被唤醒的总时间不超过1ms),则重置自旋次数,再次启动自旋,尝试获取锁。如果自旋结束后,该协程还是没有获取到锁,则回到步骤(3),开始新一轮循环。