可以从多个线程安全地访问静态数组吗?

J..*_*... 12 delphi multithreading delphi-xe2

如果保证每个线程只读/写一个特定的数组子集,多个线程可以在同一个(静态)数组上工作,而不需要求助于关键部分等?

编辑 - 这是针对非参考计数类型的数组及其记录/打包记录的特定情况.

如果是,有任何警告吗?

我的直觉是肯定的,但我的直觉有时可能是一个不可靠的信息来源.

Dav*_*nan 8

假设:

  1. 你有一个数组实例(静态或动态),和
  2. 数组的元素是纯值类型(即不包含引用),和
  3. 每个线程都在不相交的子阵列上运行,并且
  4. 当线程在其上运行时,系统中的任何其他内容都不会写入数组.

有了这些条件,我相信你的数据结构和线程模式都能满足这些条件,那么所有算法都是线程安全的.

  • @J ......是的,这是正确的.只要每个线程对该线程专用的数据进行操作,那么算法就是线程安全的. (2认同)

Arn*_*hez 7

不,在某些情况下,这可能不是线程安全的.

我看到至少有两个原因.

1.它将取决于静态数组内容.

如果您使用某些非引用计数类型(例如double, integer, bytes, shortstring),则在大多数情况下不会出现任何问题(至少在读取/仅读取数据时).

但是如果你使用一些引用计数类型(比如string, interface,或嵌套的动态数组),你将不得不处理线程安全.

那是:

TMyType1: array[0..1] of integer; // thread-safe on reading
TMyType2: array[0..1] of string;  // may be confusing
Run Code Online (Sandbox Code Playgroud)

附加说明:如果您string实际上在静态数组的某些子部分之间共享,则可能会混淆引用计数.除非你明确地要求UniqueString()每个人(在一个关键部分内,我怀疑).对于数组doubleinteger,您将不会遇到此问题.

2.这取决于访问并发性

读取访问应该是线程安全的,即使对于引用计数类型,但并发写入可能会令人困惑.对于a string,您可能会在某些随机情况下出现GPF问题,尤其是在多核CPU上.

一些安全的实施可能是:

  • 使用关键部分(尽可能小,以减少开销)或其他保护结构;
  • 使用Copy-On-Write或内容的私有每个线程副本,可以肯定;
  • 最新说明(不是安全性,而是性能):在多个CPU之间共享阵列可能会因CPU之间的缓存同步而导致性能下降.使用分离的数组时,性能有时要好得多,确保它们的L1缓存窗口不会在CPU之间共享.

请注意,在客户端,此类问题可能是调试的噩梦:多线程并发问题可能会随机发生,并且很难跟踪.除非您有明确且经过验证的性能问题,否则更安全,更好.

附加说明:对于静态数组double的特定情况,只有一个线程访问数组的子部分,它是线程安全的.但是在所有情况下都没有绝对的线程安全规则,即使对于静态数组也是如此.只要您使用一些引用计数类型或某些指针,您就可能遇到随机问题.