13

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

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

如果是,有什么注意事项吗?

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

4

2 回答 2

9

假设:

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

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

于 2012-04-16T14:50:43.930 回答
8

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

我至少看到两个原因。

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

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

2. 取决于访问并发

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

一些安全的实施可能是:

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

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

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

于 2012-04-16T14:09:14.207 回答