共享资源多线程读写未用同步,是否需mutex及操作是否存在未定义行为?
这个操作是安全的,不属于未定义行为
你的场景完全符合C++标准的内存模型保证,不用纠结是否需要mutex——这里根本不需要。
核心原因:join()的语义保证
当你调用thread.join()并成功返回时,C++标准明确了两个关键同步规则:
- 目标线程(
changeX)的所有执行操作都已完成,不会再对x做任何修改 - 目标线程中对
x的所有修改,在主线程中都是可见且有序的
换句话说,join()相当于一个内置的内存屏障,它确保了目标线程的所有内存写入操作,都能被后续主线程的读取操作看到,完全不会因为编译器优化或者CPU缓存一致性问题导致"看不到修改"的情况。你的assert(x !=5)是完全可靠的,不会出现意外失败(除非changeX线程本身没修改x,但那是逻辑问题,不是并发问题)。
为什么不需要mutex?
mutex的核心作用是保护并发访问——也就是当多个线程同时对同一数据进行读/写、写/写操作时,需要用mutex来保证操作的原子性和内存可见性。但你的场景里:
changeX线程运行时,主线程卡在join()上,根本没有访问x- 主线程访问
x时,changeX线程已经彻底终止,不可能再修改x
两者完全是顺序执行的关系,没有任何并发访问的场景,所以mutex在这里是多余的。
你之前觉得不安全的可能原因
你提到"根据C++经验认为不安全",大概率是混淆了两种场景:
- 没有同步的并发读写:如果主线程不调用
join(),直接在启动changeX后就读x,那才是未定义行为——编译器可能会把x的读取优化到线程启动前,或者CPU缓存导致看不到修改 - 你的场景是线程执行完成后再读取,这是标准明确保证安全的情况
额外补充
如果你的场景变成多个线程同时读写x(比如主线程在changeX运行时也读/写x),那必须用mutex、atomic或者其他同步机制。但当前这种"先等线程做完所有修改,再读取"的模式,完全依赖join()的同步保证就足够了。
内容的提问来源于stack exchange,提问作者UKMonkey
相关产品推荐
相关产品推荐

