So we need a shell around the global variables so that no other thread can access. When you are using VCL components, which are generally not thread-safe. A technique for communicating between threads in a Delphi application, without. A simple approach to safely passing data while using multi-threading. Only by one thread, there's no need to use local variable because a.
I declared two global variables:
These variables are written only in the main thread, and read in other threads. In this case, are these variables thread safe?
You are probably saying about atomic variables. Integer and Boolean variables are atomic. Booleans (bytes) are always atomic, integers (32-bits) are atomic because the compiler properly aligns them.
Atomicity means that any read or write operation is executed as a whole. If a thread A executes atomic write and a thread B atomic read of the same data at the same time, the data read by thread B is always consistent - it is impossible that some bits read by thread B are obtained from the current write operation and some bits from the previous write (by thread A)
But atomicity does not mean thread safety - you can easily write unsafe code with atomic variables. A variable itself cannot be threadsafe - only a code as a whole can be (or not) threadsafe.
As long as there is only one thread that can write to them, then yes, they're thread safe. The real problem with thread safety is two threads trying to modify a value at the same time, and you won't have that here.
If they were larger, like records or arrays, you might have issues with one thread trying to write a value, getting partway through, then getting context-switched and another thread reads partial (and therefore corrupt) data. But for individual boolean (1 byte) and integer (4 byte) values, the compiler can automatically align them in such a way that the CPU can guarantee that all reads and writes to them are atomic, so that isn't a problem here.
Simple types are 'thread-safe' as long as they can be read in a single read (or written in a single write) from the memory. I'm not sure if it's defined by the CPU memory bus width, or their 'integer' size (32 bits vs 64 bits cpu). Maybe someone else can clarify that part.
I know the read size nowaday is at least 32 bits. (Back in the Intel 286 days, it was only 8 bits at a time).
There is 1 thing to know about this though. Even though it can read 32 bits at a time, it cannot start a read at just any address. It needs to be a multiple of 32 bits (or 4 bytes). So, even an integer could be read in 2 subsequent reads if it's not aligned to 32 bits. Thankfully, the compiler will align pretty much all fields to 32 bits (or even 64 bits) automatically.
There is an exception to this though, packed records are never aligned, and thus, even an integer in such a record wouldn't be thread safe.
Because of their size, int64 are not thread safe either. The same can be told about most floating types. (Except Single I believe).
Now, with all that in mind, there is some situation where you could actually write a global variable from multiple thread and still be 'thread-safe'.
For example,
here, you could call the routine TestValue from multiple threads and you wouldn't corrupt the LastGoodValueTested variables. It could happen that value that is written to the variable wouldn't be the very, very last though. (If a thread context switch happen between ValueGood(aiValue) and the assignation). So, depending on the needs, it may/may not be acceptable.
Now,
Here, you can actually corrupt the counter because it's not a unary operation. You first read the variable. Then add 1 to it. Then you save it back. A thread context switch can happen in the middle of those operation. So that is a case that requires synchronization.
In that case, it could be rewritten to
I would think this is slightly faster than using critical sections... But I'm not sure.
No they are not are thread safe, you must access such variables using for example a critical section, using InitializeCriticalSection, EnterCriticalSection and LeaveCriticalSection functions
Not the answer you're looking for? Browse other questions tagged multithreadingdelphithread-safety or ask your own question.
Ranch Hand
posted 13 years ago
Hi all, Are local variables always thread safe ? and if so why is this ? My understanding is it is because they are not stored on the stack. But if they are not on the stack, where are they stored ? thanks in advance, J.C
Ranch Hand
posted 13 years ago
Local variables are thread-safe, in that no other thread can get at them. You may consider them to be stored on the stack for that thread, though Java programmers should rarely concern themselves about such low-level details. You have to be careful not to read too much into this 'thread-safe' nature of local variables. Most importantly, if your local variable is an object reference, then it is thread-safe only to the extent that another thread can't get in and change the object reference to point to another object. But, if another thread has its own reference to the same object, it CAN get in and change the object. In Java, unlike C++ and some other languages, you cannot have an object as a local variable on a stack. Java objects are always on the heap. [ August 15, 2006: Message edited by: Peter Chase ]
Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Sheriff
posted 13 years ago
Just to expand on what Peter wrote, if you think of thread safety as applying to variables, you are thinking about it the wrong way. Thread safety is always about regulating simultaneous access to objects. So if you have a local variable and assign it an object reference like this:then it may contain a reference to an object that is also referenced by other variables in other threads. And in such a case you would need to consider thread safety issues. Whereas if you assigned it an object reference like this:then no other variable anywhere can contain a reference to that new object. In this case no thread safety issues arise -- until you assign a reference to that object to something outside the scope of the local variable... [ August 15, 2006: Message edited by: Paul Clapham ]
Ranch Hand
posted 13 years ago
Local primitives are always thread safe. Objects are never local, thus can never be assumed thread-safe because of localness.
Ranch Hand
posted 13 years ago
Thanks for the response guys, Just for clarification can you confirm the following: Local variables are stored on the stack, each thread has a reference to its own set of variables on the stack, so local variables are thread safe. Objects are stored on the heap and can be accessed by multiple threads so are not thread safe. How can the object on the heap be accessed by multiple threads unless something like JNDI is used ? thanks in advance, James Objects are never local, thus can never be assumed thread-safe because of localness.
author
posted 13 years ago
Originally posted by James Clarke: Local variables are stored on the stack, each thread has a reference to its own set of variables on the stack, so local variables are thread safe.
Yes. In fact, each thread has its own stack.
How can the object on the heap be accessed by multiple threads unless something like JNDI is used ?
You can pass references to that object around between different threads. As long as you don't do that, objects are thread safe, too, of course.
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Ranch Hand
posted 13 years ago
Ranch Hand
posted 13 years ago
Originally posted by Paul Clapham: if you assigned it an object reference like this:then no other variable anywhere can contain a reference to that new object. In this case no thread safety issues arise -- until you assign a reference to that object to something outside the scope of the local variable...
Usually true, I agree, but not always. The constructor of Thing is quite at liberty to go find other pre-existing objects and interact with them. Thing's constructor could even pass a reference to itself to another object, so that object could do stuff to the Thing in another thread.
Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Ranch Hand
posted 13 years ago
Originally posted by James Clarke: Thanks for the response guys, Just for clarification can you confirm the following: Local variables are stored on the stack, each thread has a reference to its own set of variables on the stack, so local variables are thread safe. Objects are stored on the heap and can be accessed by multiple threads so are not thread safe. How can the object on the heap be accessed by multiple threads unless something like JNDI is used ? thanks in advance, James
I would like for you to pay attention to your terms. I think there are some issues there. You can not start talking about 'local' variables, then shift to talking about objects. This is like baskets vs. apples. Maybe you want to talk about variables that refer to primitives vs. variables that refer to objects? Do you have c++ background?
Sheriff
posted 13 years ago
Originally posted by Peter Chase: Usually true, I agree, but not always...
Ah, yes. Another reason to not search out helpful-sounding mantras like 'Local variables are always thread-safe', but instead to understand how things work. [ August 16, 2006: Message edited by: Paul Clapham ]