* Next, given what was said below, reading an LCL item is equally bad. A bit surprising but I accept it.
As MarkMLI hinted, this depends.
If you can establish, that the LCL item is a field, or variable.
An if (in case of a field) you can establish that the lifetime of its object will not end during your access; as well as the reference to that object will not change during your access.
Then you can read that field or variable.
However, you must re-establish those pre-conditions every time you update the LCL, or any package it interacts with.
Also the data may be outdated.
If reading the data requires more than one access to memory (Point x,y => read 2 fields), the data may be corrupt.
You can not relay on any relation between that field/var and any other field/var.
I.e, ever if the LCL code says
Value := xyz;
ValueIsValid := true;
"ValueIsValid" may become true
before Value gets assigned. The CPU can change that order on its own account (google read/write barriers).
So overall you are on shaky ground.
* But a local variable defined in user code ? Writing can be potentially risky, if you write and another process reads at about the same time, it may get one value or the other. Is that the problem ?
* And that same local variable, maybe we can read it from a thread ? In a time period where its not changing ? That 'feels' safe enough ....
In general, you can access your own data from any thread you want.
Ideally the other thread is aware of it. (definitely if you write to it, but in some cases for read access to)
See the "ValueIsValid" example above. This applies here to.
Also obviously
If obj <> nil then FreeAndNil(obj);
does not work, if 2 threads do attempt to run this.
They could both see "obj <> nil" true. (even without the CPU doing some optimizations)
Even a simple
GlobalCnt := GlobalCnt + 1;
does not work, because after ThreadA has read the value, but before it writes it back, ThreadB may also have read it. And ThreadB will then add one to the not yet updated value.
So overall only one of the 2 adds, will be in the final result.
For those things you can use the InterlockedExchange / Increment / ....
But, if you have ONE global variable, that can be read or written in a single mem access. And if only ONE thread writes to it.
Then other threads can safely read it.
Again, so long as they do not relay that any other date is up to date, based on the value that they read..
And so long, as an outdated result will be ok, and caught later.
MyThread.Terminated := True;
Does exactly that. It sets a variable.
If the thread checks, and still gets false, it runs one more iteration of whatever it does. And then it will see the True, and exit.
What about some data that is hidden behind a function or property ? Code needs to be executed to 'read' that data, without having taken steps to lock access to those functions, can we risk more than one process calling such a function (to read) them at (almost) the same time ?
The code can execute in parallel. Each thread has its own stack, and local vars.
But access to any none local data, falls under the same rules as above.