从读锁切换至写锁
如果要实现一个多线程下,大部分是读操作的场景,使用读写锁(sync.RWMutex
)往往比互斥锁(sync.Mutex
)拥有更好的性能。这一点是毋庸置疑的,因为在读锁可以有多个线程共享,只需要在修改数据时保证其他线程阻塞即可。
这也就引入一个新的问题:在获取到写锁的情况下,自然只有当前的线程拥有执行权限,即使去做读操作也不会有任何问题。但是在获取到读锁的情况下,如果需要进行写入,那么可能会有一点小问题。
试想下述流程
- 获取读锁
- 检查对应项是否存在
- 对应项不存在
- 释放读锁
- 获取写锁
- 初始化对应项
- 释放写锁
在单线程的逻辑上,似乎这里没有任何问题,但是在多线程逻辑下,2~4 中的任何一个过程,执行权限都有可能被其他线程获取,并且修改对应的内容。在当前线程初始化时,实际上是丢掉了其他线程的操作数据.
为了避免这个问题,通常在获取读锁后,需要重新进行一次检查,如果还是发现没有被初始化时,才进行初始化,否则执行更新流程。
在阅读代码时曾经见过进行两次检查的场景,但是当时一直没有太明白。当自己因为类似的问题导致数据不完整时,突然明白了原因。