Delphi threads locks waits on strings operation

227 Views Asked by At

There is a simple code:

  TParallel.For(1, 8,
    procedure(i: Integer)
    var
      localstr: String;
      Data: String;
      index: Integer;
    begin
      Data := 'test1 test2';
      index := 0;
      while true do
      begin
        index := index + 1;
        localstr := copy(Data, index, 1);
        if index > 2 then
          index := 0;
      end;
    end);

It should use 8 CPU cores but it only uses 1. The reason is the system procedure for clearing a string variable:

function _UStrClr(var S): Pointer;
if AtomicDecrement(P.refCnt) = 0 then
  FreeMem(P);

AtomicDecrement() applies a lock to make sure that the string's reference count is not simultaneously decremented on different threads. But, I am absolutely sure that my strings are isolated inside the threads. Is there any way to tell TParallel not to do that?

I could use the classic low-level WinAPI calls, but that would lose the legacy code base.

1

There are 1 best solutions below

2
Remy Lebeau On

It should use 8 CPU cores

Just because you are creating 8 parallel loop iterations does not guarantee that each iteration will run on its own CPU core. It is entirely possible that some will run on the same CPU core and the OS will have to task-switch between them. Which CPU core a task runs on is up to the OS's thread scheduler.

But, I am absolutely sure that my strings are isolated inside the threads.

Your use of the strings is isolated, but the compiler/RTL's use of the strings is not. The underlying memory management is fairly thread-safe, and that means synchronizing access to a string's internal structure, in case multiple threads try to access a given string at the same time.

Is there any way to tell TParallel not to do that?

No, and it is not TParallel's fault to begin with. This is just how the RTL's internal management of strings is implemented in general. If you don't like it, don't use reference-counted strings to begin with.