2

If multiple threads are executing class procedure TDjelatBL.Test, is there going to be an exception due to accessing variable iPublic?

The point of my question is if accessing same variable/object/constant from two or more threads simultaneously will raise an exception. I assume that nature of change of variable/object does not change memory allocation like changing size of an array.

Closest question (comparing to this one) I have found is Is a Delphi global procedure threadsafe and Are Delphi simple types thread safe? but raising of an exception is never mentioned.

unit MTTest;

interface

uses
    System.SysUtils, System.Classes;

type

    TDjelatBL = class
    public
        class procedure Test;
    end;

var
    iPublic: Integer;
    StringList: TStringList;

implementation

class procedure TDjelatBL.Test;
var
    i: Integer;
begin
    StringList.Add('x');
    for i := 1 to 1000000000 do
    begin
        iPublic := iPublic + StringList.Count;
    end;
end;

initialization
    StringList := TStringList.Create;
finalization
    StringList.Free;
Community
  • 1
  • 1
Daniel Vidić
  • 164
  • 2
  • 11
  • Possible duplicate of [Are Delphi simple types thread safe?](http://stackoverflow.com/questions/5481030/are-delphi-simple-types-thread-safe) – J... Nov 03 '16 at 15:14
  • 1
    tldr: No, it won't throw an exception but it won't necessarily work like you expect. You need to protect the variable with a critical section or some other synchronization method. Two threads can read the current value at the same time, both will add their counts to it, but only the last one to write will succeed in completing the add operation, for example. ([Race condition](https://en.wikipedia.org/wiki/Race_condition#Software)) – J... Nov 03 '16 at 15:20
  • 4
    Your example will generate an exception every single time 2 threads calls it at the same time, not because of iPublic, but because of StringList. It will at the very least crash on `StringList.free`, but more likely on `StringList.Count`, and possibly on `StringList.Add` as well. – Ken Bourassa Nov 03 '16 at 15:40
  • Indeed - there's no reason to not make the stringlist a local variable. – J... Nov 03 '16 at 15:56
  • It seems that you already tested it and got an exception. Did you tested the code? It raised any exception? What exception? – EMBarbosa Nov 03 '16 at 18:33
  • @KenBourassa Well, not necessarily, but it could do so. – David Heffernan Nov 03 '16 at 21:33
  • @DavidHeffernan it's pretty much guaranteed to (at least) double free the stringlist, unless the first thread finish just as the second thread enter. I guess that whether or not an exception is raised depends on other memory allocation going on in the process... But even if it doesn't raise an exception there, it will most likely raise one further down the road as a consequence of the double free. – Ken Bourassa Nov 04 '16 at 00:11
  • @EMBarbosa, code is shortened version of my original code and it does not work correctly with stringlist (did not thinking in multitier way when doing short version of code). First sentence in David Heffernans answer is answer to my question! I am aware of a data race but it is not subject of my question. – Daniel Vidić Nov 04 '16 at 09:04
  • I have corrected code, now stringlist sholud not produce exception – Daniel Vidić Nov 04 '16 at 09:12
  • Nope, that's still going to be a problem. Why do you need a string list to produce the number 1 anyway. Do. You need more help than my answer provides. – David Heffernan Nov 04 '16 at 21:16
  • If you have more than 2 threads adding each 1e9 to a single Integer you will get an overflow exception. Aside from the thread unsafety to TStringlist – Ritsaert Hornstra Nov 06 '16 at 19:22
  • StringList is not important, I just added it to code to make a better example, but did not verified. @DavidHeffernan you have answered my question. – Daniel Vidić Nov 10 '16 at 07:20
  • If the question is answered then you might accept it – David Heffernan Nov 10 '16 at 07:35

1 Answers1

4

Simultaneous read/modify/write actions on an integer variable will not result in exceptions.

There is a classic data race condition with your code. But there will be no exception. Use InterlockedIncrement to avoid the data race.

Using a global variable for the string list is a problem. Expect exceptions when two threads try to use that single variable simultaneously. That variable should be a local variable, and then that particular problem is resolved.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490