You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何安全正确用Interlocked函数/TInterlocked原子写入无符号变量?A/B是否线程安全?

原子化写入无符号变量的正确方式及代码分析

一、安全原子化写入无符号变量的方法

在Delphi里用Interlocked系列函数或TInterlocked类做无符号变量的原子写入,关键得让原子函数直接操作目标变量的内存地址——原子操作是靠硬件级内存访问控制实现的,必须直接碰变量的内存空间才行。
具体到UInt64类型的变量:

  • 可以把变量的地址强制转成PInt64(或者PUInt64,部分Delphi版本支持),传给InterlockedExchange64或TInterlocked.Exchange;
  • 绝对不能传变量的临时值拷贝,必须传内存引用或指针。

二、代码里(A)(B)(C)(D)的实际效果

(A)和(B)完全无效,无原子性可言

TInterlocked.Exchange(Int64(tLastReload),1);  //A
InterlockedExchange64(Int64(tLastReload),2);  //B

这两行代码连原变量tLastReload都改不了,更别说原子性和线程安全了:

  • Int64(tLastReload)是把变量的值转成Int64临时值,传递给原子函数的是这个临时值的内存(栈上的临时空间),和原变量tLastReload没关系;
  • 原子函数操作的是临时值,原变量纹丝不动,自然不存在任何线程安全保障。

(C)和(D)是正确的原子操作写法

TInterlocked.Exchange(PInt64(@tLastReload)^,3); //C
InterlockedExchange64(PInt64(@tLastReload)^,4); //D

这两行是安全的,具备完整的原子性和线程安全性:

  • @tLastReload拿到原变量的内存地址,PInt64(@tLastReload)^解引用后直接指向原变量的内存;
  • UInt64和Int64都是8字节连续存储,内存布局完全一致,强制转指针不会有问题;
  • 原子函数直接操作原变量的内存,硬件层面保证了写入操作不会被线程打断,不会出现读写冲突。

三、是否必须用(C)或(D)的写法

是的,必须用这类写法。只有让原子函数直接访问目标变量的内存地址,才能触发硬件级的原子操作。像(A)(B)那样传临时值的做法完全是无效操作,既改不了目标变量,也没有任何线程安全作用。

内容的提问来源于stack exchange,提问作者vincent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.05 12:12:32