I've heard that i++ isn't a thread-safe statement since in assembly it reduces down to storing the original value as a temp somewhere, incrementing it, and then replacing it, which could be interrupted by a context switch.
However, I'm wondering about ++i. As far as I can tell, this would reduce to a single assembly instruction, such as 'add r1, r1, 1' and since it's only one instruction, it'd be uninterruptable by a context switch.
Can anyone clarify? I'm assuming that an x86 platform is being used.
To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.
A thread-safe version should be used if you install PHP as an Apache module in a worker MPM (multi-processing model) or other environment where multiple PHP threads run concurrently - simply put, any CGI/FastCGI build of PHP does not require thread safety.
So what do I choose? If you choose to run PHP as a CGI binary, then you won't need thread safety, because the binary is invoked at each request. For multithreaded webservers, such as IIS5 and IIS6, you should use the threaded version of PHP.
Not thread safe: Data structures should not be accessed simultaneously by different threads.
You've heard wrong. It may well be that "i++"
is thread-safe for a specific compiler and specific processor architecture but it's not mandated in the standards at all. In fact, since multi-threading isn't part of the ISO C or C++ standards (a), you can't consider anything to be thread-safe based on what you think it will compile down to.
It's quite feasible that ++i
could compile to an arbitrary sequence such as:
load r0,[i] ; load memory into reg 0 incr r0 ; increment reg 0 stor [i],r0 ; store reg 0 back to memory
which would not be thread-safe on my (imaginary) CPU that has no memory-increment instructions. Or it may be smart and compile it into:
lock ; disable task switching (interrupts) load r0,[i] ; load memory into reg 0 incr r0 ; increment reg 0 stor [i],r0 ; store reg 0 back to memory unlock ; enable task switching (interrupts)
where lock
disables and unlock
enables interrupts. But, even then, this may not be thread-safe in an architecture that has more than one of these CPUs sharing memory (the lock
may only disable interrupts for one CPU).
The language itself (or libraries for it, if it's not built into the language) will provide thread-safe constructs and you should use those rather than depend on your understanding (or possibly misunderstanding) of what machine code will be generated.
Things like Java synchronized
and pthread_mutex_lock()
(available to C/C++ under some operating systems) are what you need to look into (a).
(a) This question was asked before the C11 and C++11 standards were completed. Those iterations have now introduced threading support into the language specifications, including atomic data types (though they, and threads in general, are optional, at least in C).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With