代码之家  ›  专栏  ›  技术社区  ›  curiousguy

什么可以保证两个无关线程中的不同无关对象不存在(不可避免的)竞争条件?

  •  0
  • curiousguy  · 技术社区  · 5 年前

    当不同的线程只使用不相关的对象,字面上不共享任何东西,它们就不能有竞争条件,对吗?很明显。

    实际上,所有线程都共享一些东西:地址空间。不能保证一个线程使用的内存位置不会在另一个时间分配给另一个线程。对于动态分配的对象,甚至对于自动对象来说,这可能是正确的:没有处方,多个线程的“栈”(函数的本地对象)的内存空间预先分配(甚至懒惰),不相交,并表示为通常的线性“堆栈”;它可以是任何具有堆栈(FILO)行为的东西。因此,用于存储自动对象的内存位置可以稍后被另一线程中的另一个自动对象重用。

    这本身似乎是无害的和乏味的,因为房间是如何为自动对象只在缺少房间时(非常大的自动数组或深度递归)才是重要的。

    同步呢?不相关的不相交线程显然不能使用任何C++同步原语来确保正确的同步,因为根据定义,没有(同步)(on),所以没有。 以前发生过 将在线程之间创建关系。

    如果实现重用 foo() (包括 i 破坏局部变量和退出 英尺() 在线程1中存储 bar() 线程2?

    void foo() { // in thread 1
       int i;
       i = 1;
    }
    
    void bar() { // in thread 2
       int i;
       i = 2;
    }
    

    没有 以前发生过 之间 i = 1 i = 2 .

    这会导致数据竞争和未定义的行为吗?

    换言之,所有多线程程序是否都有可能根据用户无法控制的实现选择产生未定义的行为,这些行为是不可预见的,并且存在着他无能为力的竞争?

    0 回复  |  直到 5 年前
        1
  •  4
  •   user2357112    5 年前

    C++内存模型的行为不像你想象的那样。例如,它具有内存位置,但引用N47 13草案部分第3款:

    内存位置 是标量类型的对象或相邻位字段的最大序列 非零宽度。[ 注: 语言的各种特性,如引用和虚拟函数,可能涉及 程序不能访问但由实现管理的附加内存位置。 艾斯 期末笔记 两个或多个执行线程(62.2)可以访问单独的内存位置而不干扰。 彼此之间。

    因此,通过C++内存模型,在不同线程中的两个不同的对象永远不会被认为具有相同的内存位置,即使在物理机器级别上,在另一个RAM被分配后,在相同的RAM中分配一个。

    通过C++内存模型,你问的情况不是数据竞争。实现必须采取任何必要的步骤来确保这是安全的,不管硬件的内存模型如何。

        2
  •  2
  •   Yakk - Adam Nevraumont    5 年前

    物理机器的“相同地址”对C++内存模型是不可抵抗性的。C++内存模型谈论抽象机器的行为。抽象机器中的地址基本上是不可比拟的,即使它们在不同的时间有相同的机器地址。

    C++抽象机中的竞争条件谈论的是它的操作,而不是物理机器上的操作。编译器的任务是确保C++代码的抽象机器行为的物理机器实现是一致的。

    如果它做了一些奇怪的事情,比如在线程之间重用堆栈地址空间,那么它会做任何它必须做的事情,以保持访问抽象机中不相关变量的竞争条件的缺乏。这些都不发生在C++代码级别;没有C++代码(除了可能在 namespace std )涉及。