仅执行只读操作时是否需要使用互斥锁?C多线程场景咨询
关于多线程标志位同步的问题
你的核心问题不是原子性(int的单次读写在多数CPU架构上是原子操作),而是内存可见性——如果不对标志位做任何同步处理,子线程可能永远看不到主线程修改后的标志位值。
原因是现代CPU的缓存机制:子线程会把标志位的值缓存到自己核心的高速缓存里,主线程修改的是主存里的值,子线程不会主动去主存重新读取,导致循环无法退出。
你不想用互斥锁没问题,但不能直接用普通的int标志位,得做以下处理之一:
- 把标志位声明为原子类型:用
_Atomic int flag = 1;(C11及以上标准支持),原子操作会自动保证内存可见性,开销比互斥锁小很多,几乎不影响性能。 - 如果不能用C11原子,手动插入内存屏障:主线程写标志位后执行
__sync_synchronize();(GCC扩展),子线程每次读标志位前也执行这个指令,强制CPU同步缓存。 - 别用普通
volatile int,C标准里volatile只保证不被编译器优化掉,但不保证线程间的内存可见性,在多线程场景下靠它是不安全的。
另外补充:主线程在调用pthread_join()前修改标志位,pthread_join()本身是同步点,理论上会让主线程的内存修改对其他线程可见,但这依赖具体实现,不能靠这个来保证,还是要给标志位做显式的同步处理才是标准、可移植的做法。
内容的提问来源于stack exchange,提问作者Simao
相关产品推荐
相关产品推荐

