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

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

本文关键字:成员 是否 同步 两个 对象 访问      更新时间:2024-05-24

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

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

您要查找的关键字是内存模型。

非位字段成员是不同的内存位置;读取/写入不同成员不存在种族条件。

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

但对非位字段的不同成员的访问(读或写(不会触发这种情况。

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

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

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

1.如果你只从不同的线程读取A和B,就没有同步
2.如果一些线程读取AB,而一些线程写入AB,就应该有同步,在这里你可以使用两个读/写锁来避免在访问A或B时相互影响。你可以使用std::shared_mutex实现读/写锁定