最近面试 经常问到多线程的问题,如多个线程操作一个数据,如何保证数据同步一致,如果多线程加锁后,如何避免加锁?传统的锁机制虽然能解决大部分同步问题,但也有很多问题?如死锁,性能下降;所以最后问题导向都会朝着无锁问,无锁也有很多种无锁算法,本文就主要介绍 CAS 无锁算法,CAS不仅避免了传统锁的许多问题,还提高了系统的整体性能。本文将详细介绍CAS的基本原理、C++中的实现、应用场景、注意事项以及总结。
hrp@ubuntu:~$ sudo perf stat -e context-switches ./cas Final counter value: 100000000 Time taken: 16679 milliseconds
Performance counter stats for './cas':
3,413 context-switches
16.681459973 seconds time elapsed
131.787816000 seconds user 0.027979000 seconds sys
hrp@ubuntu:~$ sudo perf stat -e context-switches ./mutex Final counter value: 100000000 Time taken: 7010 milliseconds
Performance counter stats for './mutex':
739,273 context-switches
7.012276162 seconds time elapsed
11.464533000 seconds user 15.450764000 seconds sys
atomic 中的两个接口
atomic 库,提供了两个接口 用来实现 CAS
**compare_exchange_weak**:
可能因为硬件中断或其他原因失败,即使预期值与当前值匹配。
通常更高效,因为可以在某些架构上生成更轻量级的指令。
需要在循环中使用,因为可能需要多次尝试。
**compare_exchange_strong**:
只有当预期值与当前值不匹配时才会失败。
通常生成更复杂的指令,以确保强保证。
无需在循环中使用,但可能在高竞争环境下性能较差。
两者耗时比较(差距很小)
1 2 3 4 5 6 7 8 9 10 11
#compare_exchange_strong hrp@ubuntu:~$ g++ cas1.cpp -o cas -pthread && ./cas Final counter value: 100000000 Time taken: 17137 milliseconds
#compare_exchange_weak hrp@ubuntu:~$ vi cas1.cpp hrp@ubuntu:~$ g++ cas1.cpp -o cas -pthread && ./cas Final counter value: 100000000 Time taken: 17074 milliseconds