multithreading - 在 Delphi 线程之间共享 Native 变量

标签 multithreading delphi shared-variable

我假设如果线程之间的共享变量具有 native 类型,则原子性应该可以完成这项工作。

但是根据下面代码的输出,情况并非如此,至少对于 delphi 来说是这样。

线程 t1 只是将计数器递增 10M 次。 同时,线程 t2 将计数器递减 10M 次。 所以最后的预期计数器值是 0,但我每次读取的值都不同。

在 Delphi 中的线程之间共享 native 变量而无需锁定的正确方法是什么?

procedure TForm1.Button1Click(Sender: TObject);
var
  t1, t2: TThread;
  Counter: NativeInt;
begin
  Counter := 0;

  // first thread to increment shared counter
  t1 := TThread.CreateAnonymousThread(
    procedure ()
    var
      i: Integer;
    begin
      for i := 1 to 10000000 do
        Inc(Counter);
    end
  );

  // second thread to decrement shared counter
  t2 := TThread.CreateAnonymousThread(
    procedure ()
    var
      i: Integer;
    begin
      for i := 1 to 10000000 do
        Dec(Counter);
    end
  );

  t1.FreeOnTerminate := false;
  t2.FreeOnTerminate := false;

  // start threads
  t1.Start;
  t2.Start;

  // wait for them to finish
  t1.WaitFor;
  t2.WaitFor;

  t1.Free;
  t2.Free;

  // print the counter, expected counter is 0
  Caption := IntToStr(Counter);
end;

最佳答案

对齐变量的读写是原子的。但问题是,当您使用 incdec 时,您既在读取又在写入。通过执行两次内存访问,复合操作不再是原子的。

改用原子增量函数。 TInterlocked 类方法,或 AtomicIncrement

NativeInt 而言,这是指它的大小。它是一个与指针大小相同的整型。因此,32 位进程中的 32 位,64 位进程中的 64 位。这些类型很少用于纯 Delphi 代码,通常用于与第三方库的互操作,这些第三方库可能使用指针大小的整数声明句柄类型。

关于multithreading - 在 Delphi 线程之间共享 Native 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48391309/

相关文章:

C++线程和简单的阻塞机制?

java - 多线程概念

multithreading - 德尔福TThreadPool : wait for free thread slot before proceeding with code

delphi - 为什么 TForm.SetBounds 仅在设计时将 TForm.Position 设置为 poDefault 时才能正常工作

c - 如何在线程之间共享变量?

python - 多处理共享变量

Python:为什么这里的进程之间共享多进程锁?

java - 如何知道 Android Java 线程何时完成其任务?

php - 使用 phpbrew 使用 pthreads 构建 PHP

C代码在Delphi中返回不同的结果?