Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是什么保证两个不相关线程中的不同不相关对象不会';你没有(不可避免的)比赛条件吗?_C++_Multithreading_Language Lawyer_Memory Model_Data Race - Fatal编程技术网

C++ 是什么保证两个不相关线程中的不同不相关对象不会';你没有(不可避免的)比赛条件吗?

C++ 是什么保证两个不相关线程中的不同不相关对象不会';你没有(不可避免的)比赛条件吗?,c++,multithreading,language-lawyer,memory-model,data-race,C++,Multithreading,Language Lawyer,Memory Model,Data Race,当不同的线程只使用不相关的对象,并且实际上不共享任何东西时,它们不能有竞争条件,对吗?很明显 实际上,所有线程都共享一个东西:地址空间。不能保证一个线程使用的内存位置不会在其他时间分配给另一个线程。对于动态分配的对象,甚至是自动对象,内存也是如此:没有规定多线程的“堆栈”(函数的本地对象)的内存空间是预先分配的(甚至是惰性的)、不相交的,并表示为通常的线性“堆栈”;它可以是任何具有堆栈(FILO)行为的对象。因此,用于存储自动对象的内存位置以后可以被另一个线程中的另一个自动对象重用 这本身似乎非

当不同的线程只使用不相关的对象,并且实际上不共享任何东西时,它们不能有竞争条件,对吗?很明显

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

这本身似乎非常无害和无趣,因为只有在缺少空间(非常大的自动数组或深度递归)的情况下,如何为自动对象留出空间才很重要

同步呢?不相关的不相交线程显然不能使用任何C++同步原语来确保正确的同步,因为根据定义,没有(同步)(on),所以在线程之间创建关系之前不会发生任何事情。 如果在销毁局部变量并退出线程1中的
foo()
后,实现重用
foo()
(包括
i
的位置)堆栈的内存范围来存储线程2中的
bar()

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

void bar() { // in thread 2
   int i;
   i = 2;
}
i=1
i=2
之间之前没有发生过任何事件


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


换句话说,所有的多线程程序都有可能基于用户无法控制的、不可预见的、不可竞争的执行选择而具有未定义的行为吗?

< P>物理机器的“相同地址”对C++内存模型是不可抵赖的。C++内存模型讲述了抽象机器的行为。抽象机器中的地址在基本上是不可比较的,即使它们在不同的时间具有相同的机器地址

<> > C++抽象机中的竞争条件是关于它的操作,而不是物理机器上的操作。编译器的任务是确保C++代码的抽象机器行为的物理机器实现符合。
如果它做了一些奇怪的事情,比如重用线程之间的堆栈地址空间,那么它会尽其所能来保持在抽象机器中访问无关变量时不存在争用条件。所有这些都不会发生在C++代码级;没有C++代码(除了可能在代码>命名空间STD< /COD>)中。

< P> C++内存模型的行为不像你所期望的那样。例如,它有内存位置,但引用N4713草案第6.6.1节第3段:

内存位置可以是标量类型的对象,也可以是所有具有标量类型的相邻位字段的最大序列 非零宽度。[注:语言的各种功能,如引用和虚拟函数,可能涉及 程序无法访问但由实现管理的附加内存位置。 -结束说明]两个或多个执行线程(6.8.2)可以访问单独的内存位置,而不会造成干扰 彼此之间

P> >通过C++内存模型,不同线程中的两个不同的对象永远不会被认为具有相同的内存位置,即使在物理机器级别,一个在另一个内存中分配,另一个则被释放。
<>通过C++内存模型,你所问的情况不是数据竞争。无论硬件的内存型号如何,实现都必须采取必要的步骤来确保安全。

用户无法比较对象的地址,这就是您的意思?或者抽象机器不处理地址?你能描述一下那个非常抽象的“抽象机器”吗?@奇怪的是,不,这不适合这样的回答,更不用说评论了。C++标准指定程序运行的抽象机器的行为;它没有具体说明混凝土机械的作用。编译器负责创建行为类似于指定给抽象机器的代码,除非代码显示为UB。要理解这台机器的一切,你必须基本上理解整个标准。竞赛条件是标准定义的一种UB。UB是根据抽象机器操作定义的。重用堆栈并不是在它里面发生的。这真的是一个简单的问题:在抽象机器中可以比较不相关对象的地址吗?@好奇不,不是与
@好奇的注释不是用来问后续问题的。晚安如果你有新的问题,在自己做了一些研究之后,使用[ask question],这句话似乎意味着两个线程可以同时使用相同的内存范围:线程1执行
void foo(){extern int g;g=1;}
和线程2执行
void foo(){extern int g;new(&g)int(2);}
当创建两个不同的对象时。@curiousguy:我认为这与对象生命周期的规则相冲突,但我没有一个标准的引用。在另一个对象上构建一个对象是合法的,这里的问题是由于缺乏同步而导致的竞争条件。即使在第二个函数中没有使用对象
g
(我的意思是调用
bar()
new(&g)int(2),它也必须是一个数据竞争结束以前存在于同一存储区域中的对象的生存期;如果在
foo
之前调用
bar
,则会出现未定义的行为<