多线程无锁写入vector:仅用atomic_fetch_or能否实现线程安全?
首先可以肯定的是,你当前的代码实现完全可以保证线程安全,下面具体拆解原因和需要注意的细节:
原子类型的本质保障:你使用的
std::atomic<uint8_t>是C标准定义的原子类型,所有针对它的原子操作(比如这里的std::atomic_fetch_or)都符合C内存模型的线程安全要求。atomic_fetch_or会以原子的方式完成「读取当前值 → 与testor1按位或 → 写入新值」的完整操作,整个过程不会被其他线程打断,完全避免了多线程并发修改同一个字节时可能出现的数据竞争。vector结构的稳定性:你的
MapVis是初始化时就固定了大小(1024*1024),并且场景中只有写入元素的操作,没有对vector本身进行结构修改(比如resize、push_back、erase等)。这很关键——如果有这些结构修改操作,vector内部的存储可能会重新分配,这时候即使元素是原子类型,vector的结构变更本身也会带来线程安全风险,但你的场景里不存在这种情况,所以vector的结构稳定性进一步保障了整体的线程安全。GCC的兼容性:GCC对C++原子操作的支持非常完善,从较早的版本开始就实现了标准规定的原子操作语义,所以你的代码编译时没有错误或警告是完全正常的,这也侧面说明代码的写法符合标准要求。
需要额外提醒的是:如果后续你的需求发生变化,比如需要添加读取操作,或者需要修改vector的大小,那就要重新评估线程安全策略,但就当前你描述的「仅多线程写入同一个字节、无读取、vector大小固定」的场景来说,这个实现是完全可靠的。
内容的提问来源于stack exchange,提问作者Ribeiro Silva

