← 返回首页

Go中为什么要设计nil和expunged两种删除状态?

设计nil和expunged这两个状态,是为了解决在sync.Map的"读写分离"架构下,如何高效、无锁地处理"删除"操作。

因为read map本身是只读的,我们不能直接从中删除一个key。所以,当用户调用Delete时,如果这个key只存在于read map中,系统并不会真的删除它,而是将它的值标记为一个特殊的"已删除"状态,这个状态就是expunged。后续的读操作如果看到这个expunged标记,就知道这个key其实已经不存在了,直接返回nil, false。

而nil则是一个中间状态,主要用于dirty map和read map的同步过程,表示这个key正在被删除或迁移。

简单来说,这两个状态就像是在只读的read map上打的"逻辑删除"补丁。它避免了因为一次Delete操作就引发加锁和map的整体复制,把真正的物理删除延迟到了dirty map"晋升"为read map的那一刻,是典型的用状态标记来换取无锁性能的设计。