Reputation: 71008
I believe I understand the behavior of atomic properties (and vs nonatomic ones) but I am somewhat confused by frequent reference to the notion that atomicity "does not guarantee thread safety". This statement, made often in the context of explaining atomic properties confuses me a bit, because to my read, in the obvious sense, thread safety at the property is exactly what you're getting (though no more).
My understanding is that:
An atomic
property (which is the default, versus an explicit nonatomic
) is guaranteed to never read back a garbage value due to multiple writer threads. In other words, if the write of the value itself requires multiple steps (like multiple word writes in memory), that write will be atomic. Thus a read of the property from a given thread will always reflect a value that was written in its entirety at some point in the past, although of course a subsequent read may show some different value.
If reading (or indeed writing) a property is part of an operation that requires any further guarantees-- for example, updating two properties that are semantically linked, or needing to act on the current value of a property which must be assumed to be held constant until the act is complete-- then further locking or synchronization on the part of the programmer is required for the semantics overall to be thread safe.
In other words, the writing and reading of the atomic property itself is, in fact, "thread safe" (protected from corruption by multiple writers) but of course that protection doesn't extend to any broader logic.
atomic
property actually useful? I could contrive some simple examples where a property is some sort of counter or changing object that doesn't need to reflect current state, etc, but those seem uncommon versus multithreading scenarios where you really do need explicit locking around the access-- in which case you could have just used nonatomic
on the actual property all along. NSLock
doesn't guarantee thread safety or synchronized
doesn't guarantee thread safety-- a warning for the uninitiated? Otherwise it seems a confusing designation since the very point of these synchronization mechanisms is that they are for use in thread safe design and they are known to be reliable in their designed operation. Rob Napier's answer here suggests agreement with #2 above. Would appreciate someone well versed in practical usages of atomic
to let me know if I've got the right idea here.
Upvotes: 1
Views: 420
Reputation: 437432
In other words, the writing and reading of the
atomic
property itself is, in fact, “thread safe” (protected from corruption by multiple writers) but of course that protection doesn't extend to any broader logic.
- Is this an accurate understanding?
Largely yes.
I would shy away from using the term “thread safe” in that context, though, especially in the context of objects, because the notion that a pointer is not corrupted is a far cry from any practical sense of thread safety of the object itself, much less the broader application logic.
- Under what broad circumstances is an atomic property actually useful? I could contrive some simple examples where a property is some sort of counter or changing object that doesn't need to reflect current state, etc, but those seem uncommon versus multithreading scenarios where you really do need explicit locking around the access-- in which case you could have just used nonatomic on the actual property all along.
They can be useful when dealing with primitive data types in specific scenarios (e.g., a boolean state property designating whether some background process is done). They also can be useful in special cases where you are dealing with immutable, stateless objects.
But in most multithreaded scenarios, atomic
properties generally fail to achieve thread safety.
- Why exactly do people consistently say that atomicity doesn't “guarantee thread safety”? That seems only true in the same way that an
NSLock
doesn’t guarantee thread safety or synchronized doesn't guarantee thread safety-- a warning for the uninitiated? Otherwise it seems a confusing designation since the very point of these synchronization mechanisms is that they are for use in thread safe design and they are known to be reliable in their designed operation.
We do this because there were people (e.g. https://stackoverflow.com/a/17571453/1271826) who incorrectly suggest that atomic
properties achieve thread-safety when it almost always fails to do so. Back in the day, it seemed like whenever someone asked a question about thread safety, someone would chime in with “oh, use atomic
properties”. There seemed to be a perennial conflation of “thread safety” and the modest protection against corruption that atomic
offers.
So, yes, “has nothing to do with thread safety” is a bit strong. But in the vast majority of cases, atomic properties fail to achieve thread safety, and in the presence of properly implemented synchronization (such as locks, @synchronized
, GCD, etc.), just introduce unnecessary overhead.
This is very different than the other synchronization mechanisms (such as locks, etc.). With proper implementation of these mechanisms, one invariably can achieve thread safety. But in many cases (most cases?) atomic
simply won’t do the job. Sure, atomic
can mitigate one very narrow type of corruption of values/pointers, but that generally doesn’t make one’s code thread safe.
Upvotes: 2
Reputation: 7588
It is not thread safe, that means if thread A is accessing your variable, then thread B, C, D also can access and make changes to it. So at the end of thread A, there is no knowing what the variable holds.
Upvotes: 0