mutex vs atomic
很多文章都有介绍相比于互斥锁(mutex),原子操作的消耗更小、性能更高。
那么:
真的是这样吗?是所有场景都这样吗?
为什么会这样呢?
锁和原子操作分别适合哪些场景呢?
原子操作是怎么实现的?
原子操作是利用硬件(处理器)支持的原子操作来实现的,是属于低级别的同步操作,所以通常更快,但功能比较有限。
原子操作是简单的施加内存屏障。不能暂停线程的执行。所以没有线程上下文切换的开销。
但如果是争用非常频繁的场景,就会导致大量线程一直占着 CPU 在死循环,比较浪费 CPU 资源。
原子操作通常用于进行简单的操作,比如递增一个计数器、更新一个 flag、Compare-And-Change。
锁是怎么实现的?
锁的实现更依赖于操作系统,比如 windows 和 linux 对锁的实现方式就可能不同。不过底层也是依靠原子操作来实现的。相对于原子操作,锁是更高级别、更上层的实现。
锁可以暂停线程,把 CPU 让渡给其它线程来执行,但这就带来了上下文切换的开销。自旋锁可以通过一直自旋来达到一直占用 CPU 的目的。
目前的锁实现大多都会先自旋一小段时间,如果仍然无法抢占到锁,就会让出 CPU 时间。
不过如果是争用非常频繁的场景,把 CPU 资源让渡给其它线程执行可能也更合理。
锁可以用来保护更复杂的操作块,而不仅是简单的计数器场景。
另外,锁因为是操作系统内核的实现,所以可以适用于多进程之间。而原子操作只能适用于单进程内的多线程之间。
该用 mutex 还是 atomic?
竞态区比较复杂的,使用 mutex。因为 atomic 的功能很有限,只能适用于比较简单的场景,比如计数器、设置一个指针的值等。
竞争比较频繁的,比较适合 mutex;否则适合 atomic。但目前也只能通过 benchmark 来得出结论,很难有其它指标能明确地说哪个更适合。
如果是多进程间同步,atomic 就不能使用了,可以使用 mutex。
参考资料:
https://coffeebeforearch.github.io/2020/08/04/atomic-vs-mutex.html
版权声明: 本文为 InfoQ 作者【Geek_44385e】的原创文章。
原文链接:【http://xie.infoq.cn/article/ef57655bbe786511af9bde14c】。未经作者许可,禁止转载。
评论