【发布时间】:2022-11-21 23:30:45
【问题描述】:
我正在使用 Delphi TThread 运行到外部设备的多个 TCP 连接。传入的数据被分解和存储。一切正常,但在审查我的代码时,我怀疑它是否是线程安全的,或者到目前为止我是否幸运......
在 TThread.Execute 方法中,我调用了一个存在于不同单元中的辅助函数,而不是任何 TThread 或其他类的成员。该函数访问缓冲区中的四个字节数据,反转字节顺序并将结果放入Single 类型的变量中(外部设备为大端)。
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 进入函数都会发生这种情况,但是解决这些变量的代码中发生的事情让我感到困惑。
为了省心,把函数变成线程类的方法是不是更好的做法?
【问题讨论】:
-
您展示的函数是完全线程安全的,只要每个线程都使用自己的
TByteBuffer调用它,而不是与其他线程共享(或者,如果共享,则对它的访问已在线程之间充分同步) . -
方法只是具有额外隐藏参数的函数。方法中没有什么比函数更线程安全或不安全的。这完全取决于函数或方法的编写方式以及它访问的共享数据类型(如果有)。如果函数或方法不直接访问任何共享数据,就像你的不一样,那么它本身就是线程安全的。但是,如果您作为参数传递的数据在多个线程之间共享,那么代码的线程安全性将取决于更广泛的上下文,而不仅仅是函数本身,就像 Remy 已经提到的那样。
-
有点不清楚你的意思是“每个进入函数的 TThread 都会发生这种情况,但是处理这些变量的代码中发生的事情让我感到困惑。”您在这里谈论的是哪些变量、哪些代码以及在什么时间?
标签: multithreading delphi thread-safety tthread