delphi 多线程线程安全

8oomwypt  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(310)

我正在使用 Delphi TThread运行多个TCP连接到外部设备。传入的数据被解剖和存储。一切工作正常,但在审查我的代码,我有怀疑它是否是线程安全或如果我只是幸运到目前为止...
TThread.Execute方法中,我调用了一个helper函数,该函数存在于另一个单元中,不是任何TThread或其他类的成员。该函数访问缓冲区中的四个字节的数据,反转字节顺序,并将结果放入Single类型的变量中(外部设备是Big Endian)。

type
  TByteBuffer = array [0 .. 255] of Byte;

function ConvBufferToSingle(Buffer: TByteBuffer; J: Byte): Single;
type
  TSingleByteArray = array [0 .. 3] of Byte;
var
  X: Single;
begin
  TSingleByteArray(X)[3] := Buffer[J];
  TSingleByteArray(X)[2] := Buffer[J + 1];
  TSingleByteArray(X)[1] := Buffer[J + 2];
  TSingleByteArray(X)[0] := Buffer[J + 3];
  Result := X;
end;

虽然这看起来很有效,但我不明白如果一个(或多个)线程在另一个线程退出之前进入该函数会发生什么。我读过关于 * 线程安全 * 与 * 重新进入 * 代码的文章,但我仍然不确定如何验证代码是线程安全的。
当函数被调用时,我相信参数会被推到堆栈上,这会发生在每个进入函数的TThread上,但是代码中对这些变量的寻址让我很困惑。
为了让您安心,将函数转换为线程类的方法是否是更好的做法?

b5buobof

b5buobof1#

该代码不是线程安全的。TSingleByteArray是托管类型。从多个线程并发读取或写入托管类型是不安全的。最简单的解决方案是使函数成为线程类的方法。这样,每个线程都有自己的函数示例,因此也有自己的TSingleByteArray。或者,您可以使用TInterlocked函数使代码线程安全。例如:

type
  TSingleByteArray = array [0 .. 3] of Byte;
var
  X: Single;
begin
  TInterlocked.Exchange(TSingleByteArray(X)[3], Buffer[J]);
  TInterlocked.Exchange(TSingleByteArray(X)[2], Buffer[J + 1]);
  TInterlocked.Exchange(TSingleByteArray(X)[1], Buffer[J + 2]);
  TInterlocked.Exchange(TSingleByteArray(X)[0], Buffer[J + 3]);
  Result := X;
end;
</code>

相关问题