1x86和x64具有强大的内存模型:http://herbsutter.com/2012/08/02/strong-and-weak-hardware-memory-models/ 至于“volatile”,我很了解,尽管它在不同的编译器中有许多不同的含义。但是,既然你谈论的是Delphi,在这里它没有意义。我的理解是,对于某些适当的“volatile”定义,Delphi使非局部变量成为易失性变量! - David Heffernan
1@dthorpe 你能对D6编译器发表评论吗?我知道当前的32位编译器在这个领域几乎无法区分。 - David Heffernan
1其他线程能够看到更改的可见性 - 不要交换指针并使用 threadvar,它看起来会有点相似。 - Arioch 'The
显示剩余6条评论
1个回答
14
14
我会说Delphi内存模型与C++内存模型相匹配。也就是说,编译器并不知道多个进程或多个线程,并且不为这些场景提供任何特殊支持。请参见"What is the C++ memory model for concurrency?"
Delphi 32位编译器确实执行像不变代码运动这样的优化,并且发出旨在避免停顿双管道的指令序列。但是,Delphi编译器没有指令调度程序或peephole优化器,因此指令重排的机会非常少。 本地变量可以登记,但对需要内存地址的变量的任何源代码引用(例如将本地变量传递给var参数或获取本地变量的地址)都会迫使编译器在使用地址之前将登录值提交到内存位置,或者可能会迫使编译器完全放弃注册变量。 Delphi 32位编译器在其优化中相当保守。从优化中获得的最大性能增益来自于注册变量和中间结果以及各种循环归纳技巧。 全局符号或驻留在全局内存中的符号(例如对象字段)上的操作不会被登记。没有“volatile”修饰符。 编译器的代码生成模式依赖于x86架构规则,即对齐地址的寄存器大小写入到全局内存的原子性。大数据,字节数据或非对齐地址的写入可能跨越缓存行并要求单个写入指令中进行两个分开的写入操作。Delphi编译器在这方面(大体上)是无意识的。 无论如何,如果您正在编写从不同线程访问共享内存的Delphi代码,则始终您有责任决定适合您情况的线程同步措施并实现它们。
- dthorpe
4
2+1. Danny,你的回答写得非常好。干得漂亮!这是我很少希望能够点赞多次的情况之一。 - Ken White
volatile
或进行同步,否则没有任何保证线程将永远看到由运行在不同核心上的线程所做的任何内存更改。这实际上经常发生。 - maaartinusthreadvar
,它看起来会有点相似。 - Arioch 'The