访问同一对象的两个不同成员是否需要同步?

Does accessing two different members of the same object need synchronization?

如果我们有一个包含两个数据成员A和B的对象;从两个不同的线程 运行 并行访问两个成员时,我们是否需要任何形式的同步?如果该对象是一个全局变量,而不是该对象是一个堆对象,使用指向其地址的指针访问,那又如何呢?

编辑: 每个线程只读取和写入一个不同的成员,一对一关联,线程数等于数据成员数,线程分别访问它们,直到它们完成并加入主线程。

对于仅由一个线程访问的数据成员,不需要同步。对于可能被线程写入的数据成员,并且 also 可能被任何其他线程访问(以任何方式),同步 is 必要。

对象是全局对象还是在堆上都没有区别,除了堆上的对象可能会被删除而其他线程仍然持有指向它们的指针——例如如果线程 1 删除了该对象,而线程 2(可能)正在访问该对象中的一个或多个数据成员,那么您就会遇到问题,因为线程 2 可能会尝试读取或写入现在空闲的内存位置数据成员曾经被定位,调用未定义的行为。 (您通常会通过在 before 创建将使用它的线程之前分配堆对象来避免该问题,并且在 after[=19= 之前不删除该堆对象] 该线程已退出,您已对其调用 join() 以确保它已消失)

1.If你只从不同的线程读取A和B,没有同步
2.If有的线程读AB,有的线程写AB,应该是同步的,这里可以使用两个read/write锁来避免访问A或B时互相影响,可以使用std::shared_mutex 实施 read/write 锁定

您要查找的关键字是memory model

非位域成员是不同的内存位置; reading/writing 不同成员没有竞争条件。

在一个线程中写入并在另一个线程中访问同一内存位置是潜在的冲突。除非满足某些要求(例如 发生在 之前),否则这是一个竞争条件,并且您的程序具有 UB(未定义的行为)。

但是访问(读取或写入)非位域的不同成员不会触发此事件。

实际规则更复杂;例如,并非所有位域都共享一个内存位置。