`const`字符串参数(线程)是否安全

Joh*_*ica 10 delphi string parameters const

这段代码

procedure MyThreadTestA(const AStr: string);
Run Code Online (Sandbox Code Playgroud)

比快

procedure MyThreadTestB(AStr: string);
Run Code Online (Sandbox Code Playgroud)

在做同样的工作时,都会传递一个指针.

但是,版本B'正确'更新了引用计数,AStr并在我更改它时进行复制.
版本A只传递一个指针,只有编译器阻止我改变AStr.

如果我在汇编程序中使用脏技巧或以其他方式规避编译器保护,则版本A不安全,这是众所周知的但是......

通过AStr引用传递作为const参数线程安全吗?
如果AStr某个其他线程中的引用计数变为零并且字符串被销毁会发生什么?

Bar*_*lly 16

不,这样的技巧不是线程安全的.Const防止add-ref,因此另一个线程的更改将以不可预测的方式影响该值.示例程序,尝试修改const以下定义P:

{$apptype console}
uses SysUtils, Classes, SyncObjs;

type
  TObj = class
  public
    S: string;
  end;

  TWorker = class(TThread)
  public
    procedure Execute; override;
  end;

var
  lock: TCriticalSection;
  obj: TObj;

procedure P(const x: string);
// procedure P(x: string);
begin
  Writeln('P(1): x = ', x);
  Writeln('Releasing obj');
  lock.Release;
  Sleep(10); // give worker a chance to run
  Writeln('P(2): x = ', x);
end;

procedure TWorker.Execute;
begin
  // wait until TMonitor is freed up
  Writeln('Worker started...');
  lock.Acquire;
  Writeln('worker fiddling with obj.S');
  obj.S := 'bar';
  TMonitor.Exit(obj);
end;

procedure Go;
begin
  lock := TCriticalSection.Create;
  obj := TObj.Create;
  obj.S := 'foo';
  UniqueString(obj.S);
  lock.Acquire;
  TWorker.Create(False);
  Sleep(10); // give worker a chance to run and block
  P(obj.S);
end;

begin
  Go;
end.
Run Code Online (Sandbox Code Playgroud)

但它不仅限于线程; 修改基础变量位置具有类似的效果:

{$apptype console}
uses SysUtils, Classes, SyncObjs;

type
  TObj = class
  public
    S: string;
  end;

var
  obj: TObj;

procedure P(const x: string);
begin
  Writeln('P(1): x = ', x);
  obj.S := 'bar'; 
  Writeln('P(2): x = ', x);
end;

procedure Go;
begin
  obj := TObj.Create;
  obj.S := 'foo';
  UniqueString(obj.S);
  P(obj.S);
end;

begin
  Go;
end.
Run Code Online (Sandbox Code Playgroud)