问题描述
当不同的线程仅使用不相关的对象并且实际上不共享任何东西时,它们就不会具有竞争条件,对吗?显然.
实际上,所有线程共享一些东西:地址空间.不能保证一个线程使用的内存位置不会在其他时间分配给另一个线程.对于动态分配的对象甚至是自动对象的内存,情况可能都是如此:没有规定多个线程的堆栈"(函数的本地对象)的内存空间是预先分配的(甚至是延迟的),不相交的并且表示为通常的线性堆栈";它可能是具有堆栈(FILO)行为的任何东西.因此,用于存储自动对象的内存位置以后可以由另一个线程中的另一个自动对象重用.
这本身似乎是无害且无趣的,因为只有在缺少空间(非常大的自动数组或深度递归)时,才为自动对象腾出空间是很重要的.
关于同步呢?显然,不相关的不相交的线程不能使用任何C ++同步原语来确保正确的同步,因为按照定义,没有什么要同步(上),因此不会在线程之间创建之前关系.
如果实现在销毁局部变量并退出线程1中的foo()
后在线程1中存储bar()
的变量后,实现重新使用foo()
堆栈的内存范围(包括i
的位置)怎么办? 2?
void foo() { // in thread 1
int i;
i = 1;
}
void bar() { // in thread 2
int i;
i = 2;
}
在i = 1
和i = 2
之间没有发生.
会导致数据争用和不确定的行为吗?
换句话说,基于用户无法控制的实现选择,所有多线程程序是否都有可能具有不确定的行为,这些选择是不可预见的,并且由于种族的原因他无能为力?
C ++内存模型的行为不像您可能期望的那样.例如,它具有内存位置,但引用了N4713草案第6.6.1节第3段:
因此,根据C ++内存模型,即使在物理机器级别上,一个线程在另一个RAM释放之后分配在同一RAM中,也永远不会认为不同线程中的两个不同对象具有相同的内存位置.
通过C ++内存模型,您所询问的情况不是数据争用.无论硬件的内存模型如何,实现都必须采取一切必要步骤以确保安全性.
When different threads only use unrelated objects and literally do not share anything they cannot have a race condition, right? Obviously.
Actually all threads share something: the address space. There is no guarantee that a memory location that was used by one thread isn't going to be allocated at some other time to another thread. This can be true of memory for dynamically allocated objects or even for automatic objects: there is no prescription that the memory space for the "stacks" (the local objects of functions) of multiple threads is pre-allocated (even lazily), disjoint and represented as the usual linear "stack"; it could be anything with stack (FILO) behavior. So the memory location used to store an automatic object can be reused later by another automatic object in another thread.
That in itself seems pretty innocuous and uninteresting as how room is made for automatic objects is only important when room is missing (very large automatic arrays or deep recursion).
What about synchronisation? Unrelated disjoint threads obviously cannot use any C++ synchronisation primitive to ensure correct synchronisation as by definition there is nothing (to) synchronize (on), so no happens before relation is going to be created between threads.
What if the implementation reuses the memory range of the stack of foo()
(including the location of i
) after destruction of local variables and exit of foo()
in thread 1 to store variables for bar()
in thread 2?
void foo() { // in thread 1
int i;
i = 1;
}
void bar() { // in thread 2
int i;
i = 2;
}
There is no happens before between i = 1
and i = 2
.
Would that cause a data race and undefined behavior?
In other words, do all multithread programs have a potential for having undefined behavior based on implementation choices the user has no control over, that are unforeseeable and with races he can't do anything about?
The C++ memory model doesn't behave like you might intuitively expect. For example, it has memory locations, but quoting the N4713 draft section 6.6.1, paragraph 3:
So by the C++ memory model, two distinct objects in different threads are never considered to have the same memory location, even if at the physical machine level, one is allocated in the same RAM after the other is deallocated.
By the C++ memory model, the situation you ask about is not a data race. The implementation must take whatever steps are necessary to ensure this is safe, regardless of the hardware's memory model.
这篇关于如何保证两个不相关线程中的不同不相关对象没有(不可避免的)竞争条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!