从读锁切换至写锁

如果要实现一个多线程下,大部分是读操作的场景,使用读写锁(sync.RWMutex)往往比互斥锁(sync.Mutex)拥有更好的性能。这一点是毋庸置疑的,因为在读锁可以有多个线程共享,只需要在修改数据时保证其他线程阻塞即可。

这也就引入一个新的问题:在获取到写锁的情况下,自然只有当前的线程拥有执行权限,即使去做读操作也不会有任何问题。但是在获取到读锁的情况下,如果需要进行写入,那么可能会有一点小问题。

试想下述流程

  1. 获取读锁
  2. 检查对应项是否存在
  3. 对应项不存在
  4. 释放读锁
  5. 获取写锁
  6. 初始化对应项
  7. 释放写锁

在单线程的逻辑上,似乎这里没有任何问题,但是在多线程逻辑下,2~4 中的任何一个过程,执行权限都有可能被其他线程获取,并且修改对应的内容。在当前线程初始化时,实际上是丢掉了其他线程的操作数据.

为了避免这个问题,通常在获取读锁后,需要重新进行一次检查,如果还是发现没有被初始化时,才进行初始化,否则执行更新流程。


在阅读代码时曾经见过进行两次检查的场景,但是当时一直没有太明白。当自己因为类似的问题导致数据不完整时,突然明白了原因。