并发操作固定大小std::deque的独立内存块是否线程安全?
结论先行:不会有未定义行为,不需要互斥锁
首先,咱们从C++内存模型的核心规则说起:只有当两个线程同时访问同一个内存位置,且至少其中一个是写操作,同时没有任何同步机制时,才会触发数据竞争,进而导致未定义行为。
回到你的场景,满足两个关键的安全前提:
std::deque的大小全程不变,不会触发重新分配,这意味着所有元素的内存地址从并发开始到结束都是固定的,deque内部的控制结构(比如指向各个内存块的指针数组)也不会被修改,不存在线程对deque自身结构的竞争。- 每个线程只访问完全独立的内存区域——也就是各自对应的
std::pair<CustomObj, int>元素,线程之间的操作没有任何内存重叠。
这种情况下,线程之间的读写操作完全隔离:
- 线程读取自己负责的
CustomObj,是对独立内存的读操作,没有其他线程去写这个CustomObj(你只说设置对应的int,而且是自己线程的那个); - 线程修改自己负责的
int值,是对独立内存的写操作,没有其他线程去读或写这个int。
完全符合C++内存模型中“无数据竞争”的安全条件,所以不会产生未定义行为,自然也不需要额外加互斥锁来同步。
几个需要严格遵守的前提(别踩坑)
- 绝对不能出现多个线程操作同一个
std::pair的情况——哪怕只是其中的int部分,只要两个线程碰同一个内存位置,就会有数据竞争风险。 - 必须确保整个并发期间,没有任何线程对这个
deque做插入、删除、resize、clear等会改变其大小或内部结构的操作,哪怕是只读线程也不能在结构变化时访问元素。 - 如果你的
CustomObj内部本身有共享的可变状态(比如类成员是全局变量或跨线程共享的),那读取CustomObj的操作可能需要额外考虑,但如果每个CustomObj都是元素独有的、没有跨线程共享状态,那就没问题。
内容的提问来源于stack exchange,提问作者quimnuss
相关产品推荐
相关产品推荐

