Delphi并发内存模型?

9

在Delphi中是否有类似Java内存模型的东西?为了避免误解:我指的不是像“巨大/大/小”之类的东西,而是与对其他线程的更改可见性相关的事情。


2
@David Heffernan:如果事情那么简单,就不需要内存模型了。amd64架构不能保证普通内存访问不需要特殊指令。在多核系统上,除非你使用volatile或进行同步,否则没有任何保证线程将永远看到由运行在不同核心上的线程所做的任何内存更改。这实际上经常发生。 - maaartinus
1
x86和x64具有强大的内存模型:http://herbsutter.com/2012/08/02/strong-and-weak-hardware-memory-models/ 至于“volatile”,我很了解,尽管它在不同的编译器中有许多不同的含义。但是,既然你谈论的是Delphi,在这里它没有意义。我的理解是,对于某些适当的“volatile”定义,Delphi使非局部变量成为易失性变量! - David Heffernan
2
如果英特尔/AMD“削弱”现有的x86/x64指令集内存模型,全球所有应用程序和操作系统都将崩溃。他们只能在新指令或新执行模式上“削弱”内存语义,而现有代码和编译器不使用。英特尔和AMD非常了解“选择加入”的概念。 - dthorpe
1
@dthorpe 你能对D6编译器发表评论吗?我知道当前的32位编译器在这个领域几乎无法区分。 - David Heffernan
1
其他线程能够看到更改的可见性 - 不要交换指针并使用 threadvar,它看起来会有点相似。 - Arioch 'The
显示剩余6条评论
1个回答

14
我会说Delphi内存模型与C++内存模型相匹配。也就是说,编译器并不知道多个进程或多个线程,并且不为这些场景提供任何特殊支持。请参见"What is the C++ memory model for concurrency?" Delphi 32位编译器确实执行像不变代码运动这样的优化,并且发出旨在避免停顿双管道的指令序列。但是,Delphi编译器没有指令调度程序或peephole优化器,因此指令重排的机会非常少。
本地变量可以登记,但对需要内存地址的变量的任何源代码引用(例如将本地变量传递给var参数或获取本地变量的地址)都会迫使编译器在使用地址之前将登录值提交到内存位置,或者可能会迫使编译器完全放弃注册变量。
Delphi 32位编译器在其优化中相当保守。从优化中获得的最大性能增益来自于注册变量和中间结果以及各种循环归纳技巧。
全局符号或驻留在全局内存中的符号(例如对象字段)上的操作不会被登记。没有“volatile”修饰符。
编译器的代码生成模式依赖于x86架构规则,即对齐地址的寄存器大小写入到全局内存的原子性。大数据,字节数据或非对齐地址的写入可能跨越缓存行并要求单个写入指令中进行两个分开的写入操作。Delphi编译器在这方面(大体上)是无意识的。
无论如何,如果您正在编写从不同线程访问共享内存的Delphi代码,则始终您有责任决定适合您情况的线程同步措施并实现它们。

2
+1. Danny,你的回答写得非常好。干得漂亮!这是我很少希望能够点赞多次的情况之一。 - Ken White
1
+1,非常好的回答。我想知道是否有任何计划/意图改进Delphi关于进程和线程的内存模型。顺便问一下,有人知道64位编译器是否以相同的方式工作吗? - Guillem Vicens
2
谢谢。关于64位,从我所看到的,它采用了相同的寄存器策略。@Guillem - David Heffernan
1
我无法谈论计划或意图,自2005年以来我已经脱离了圈子。 - dthorpe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接