根据数据总线设置变量来自多线程无防护

问题描述:

我在x64上使用C++多线程。我想更好地理解数据总线。我想知道如果我尝试从2个线程设置变量而没有任何防范(无互斥锁,CV,信号量和无原子)会发生什么。数据总线依赖于什么? 例如,如果我有变量:根据数据总线设置变量来自多线程无防护

int32_t i; 

如果我设置在不同的线程变量: 线程1:

i =0x11223344; 

线程2:

i =0x44332211; 

正如我知道针对x64数据总线是64位。所以变量i可以设置为1条指令。我知道这取决于编译器。我知道缓存也有影响力。我想知道只有与数据总线(没有缓存)的交互。我的问题是取决于数据总线宽度(8,16,32位)会是什么样的行为。 i的价值是多少?

+2

没有什么可以理解的。在构成当前C++标准的1400多个页面中,没有提及任何被描述为“数据总线”的东西。 –

+0

C++只是说这是未定义的行为,所以不能帮助回答问题。您需要将程序编译为汇编程序,然后查看汇编指令所做的工作,以确定代码的作用(根据编译器标志和其他内容显然会发生变化)。您应该发布汇编代码,以便答案至少可以。 – nwp

+0

我的问题是如果集合在一个指令中都是原子的。 –

不幸的答案是,你的问题没有明确的答案。

让我们从C++中离开一会儿:你想要做的是执行一个不同步的并发写入。关于这种操作的结果将会有很大的不同,这取决于许多因素。当然,目标架构扮演着重要角色。像x86这样具有强大内存模式的机器可能比PowerPC或ARM机器更宽容。但它并没有在这里结束。对齐可以起到至关重要的作用,您正在运行的计算机上的特定内存配置也可以起作用(请考虑NUMA体系结构)。所以没有一个适合所有答案的答案。这一切都非常微妙地依赖于情况,即使情况确切地知道,你经常留下的答案是:我们根本无法分辨,最终可能是任何东西(包括出现的数字) -thin-air,也就是说,这个值不是由任何并发写入操作写入的值),因为这只是硬件的构建方式。

因此,在如此高层次上讨论这个问题根本没有意义。就x86而言,指令集体系结构提供了一些保证。欢迎自己浏览the manual的相关章节。但是,如果您使用线程未知的内存访问,则无法从更高级别的语言访问这些保证。由于行为未定义,因此编译器可以执行任意数量的优化,这些优化可以以任意方式混淆生成的代码,但仍与您在代码中表达的内容一致。由于您的代码不知道并发性(根据定义,因为您使用的是非同步访问),编译器完全有权执行此操作。

所以唯一的出路是使用正确的同步,例如锁或原子。它们在语言层面上提供了一定的保证(不允许某些编译器优化),并确保这些保证一直贯穿到硬件上(通过在生成的机器代码中插入必要的同步指令)。只有当你拥有从高级语言到组成硬件的完整硅片保证链时,才能进行适当的多线程编程。从链中删除任何单个链接,整个事情就会崩溃。

+0

是的,你是适合高层的。我在考虑在和应该值应该是两个值或像字节混合像(0x11222211)之一。这样的问题可能会更好地在组装层面或者硬件层面上提问。我的问题是为了简单的好奇心。感谢细节。我会从手册中读到露水的事情。 –

+0

@Vladimir - 在x64上一个正确对齐的整数值总是一次全部写入,所以它不会被“混合”。但是,除非它是一个'atomic ',否则根本不能保证它被写入内存。此外,编译器可能会利用硬件功能并使用相同的指令来读取写入原子值,就像它为“正常”值所做的那样。它只需要确保它在适当的时候完成。 –