该函数是否需要加锁?关于pthread互斥锁读取64位变量的疑问
关于64位共享变量读取加锁的疑问
以下是原示例代码:
#include <pthread.h> pthread_mutex_t count_mutex; long long count; void increment_count() { pthread_mutex_lock(&count_mutex); count = count + 1; pthread_mutex_unlock(&count_mutex); } long long get_count() { long long c; pthread_mutex_lock(&count_mutex); c = count; pthread_mutex_unlock(&count_mutex); return (c); }
文档相关说明:
increment_count()函数使用互斥锁确保共享变量的原子更新,这一点合理。但文档称get_count()函数使用互斥锁保证64位变量count的原子读取,对此我有疑问:解锁count_mutex后,其他线程可调用increment_count()修改count,导致返回结果失效,这不可避免。那为何不直接写成无锁形式?
无锁版本代码:
long long get_count() { return count; }
解答
加锁的核心不是保证返回值永远有效,而是保证读取操作本身是原子且正确的,具体原因有这几点:
- 避免撕裂读:在32位系统上,64位变量的读取会拆成两次32位操作。如果不加锁,其他线程在两次操作之间修改变量,你读到的会是一个“半旧半新”的错误值,完全不符合变量在任意时刻的真实状态。
- 保证内存可见性:互斥锁的解锁操作会强制刷新CPU缓存,确保当前线程读到的
count是内存中的最新值,而不是缓存里的过期数据。无锁读取可能因为缓存一致性问题,拿到旧值。 - 代码可移植性:就算64位系统硬件支持64位原子读取,加锁写法能兼容所有平台,不需要依赖特定硬件特性,代码在不同架构下都能正常工作。
至于你提到的“返回后值失效”,这是多线程环境的固有特性——任何共享变量的读取结果都只代表某个瞬间的状态,后续被修改是正常的。但加锁至少能保证你拿到的是那个瞬间的完整、正确的值,而不是一个错误的撕裂值。
内容的提问来源于stack exchange,提问作者EmTor
相关产品推荐
相关产品推荐

