What do atomic
and nonatomic
mean in property declarations?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
What is the operational difference between these three?
The best way to understand the difference is using the following example.
Suppose there is an atomic string property called "name", and if you call
[self setName:@"A"]
from thread A, call[self setName:@"B"]
from thread B, and call[self name]
from thread C, then all operations on different threads will be performed serially which means if one thread is executing a setter or getter, then other threads will wait.This makes property "name" read/write safe, but if another thread, D, calls
[name release]
simultaneously then this operation might produce a crash because there is no setter/getter call involved here. Which means an object is read/write safe (ATOMIC), but not thread-safe as another threads can simultaneously send any type of messages to the object. The developer should ensure thread-safety for such objects.If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, either one of A, B or C will execute first, but D can still execute in parallel.
The last two are identical; "atomic" is the default behavior (
note that it is not actually a keyword; it is specified only by the absence of--nonatomic
atomic
was added as a keyword in recent versions of llvm/clang).Assuming that you are @synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory. (Note: @synthesize is now the default behavior in recent versions of LLVM. There is also no need to declare instance variables; they will be synthesized automatically, too, and will have an
_
prepended to their name to prevent accidental direct access).With "atomic", the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In
nonatomic
, no such guarantees are made. Thus,nonatomic
is considerably faster than "atomic".What "atomic" does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.
Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.
Adding to this:
atomicity
of a single property also cannot guarantee thread safety when multiple dependent properties are in play.Consider:
In this case, thread A could be renaming the object by calling
setFirstName:
and then callingsetLastName:
. In the meantime, thread B may callfullName
in between thread A's two calls and will receive the new first name coupled with the old last name.To address this, you need a transactional model. I.e. some other kind of synchronization and/or exclusion that allows one to exclude access to
fullName
while the dependent properties are being updated.Atomic means only one thread accesses the variable (static type). Atomic is thread-safe, but it is slow.
Nonatomic means multiple threads access the variable (dynamic type). Nonatomic is thread-unsafe, but it is fast.
Atomic properties :- When a variable assigned with atomic property that means it has only one thread access and it will be thread safe and will be good in performance perspective, will have default behaviour.
Non Atomic Properties :- When a variable assigned with atomic property that means it has multi thread access and it will not be thread safe and will be slow in performance perspective, will have default behaviour and when two different threads want to access variable at same time it will give unexpected results.
Before you begin: You must know that every object in memory needs to be deallocated from memory for a new write to happen. You can't just simply write on top of something as you do on paper. You must first erase (dealloc) it and then you can write onto it. If at the moment that the erase is done (or half done) and nothing has yet been wrote (or half wrote) and you try to read it could be very problematic! Atomic and nonatomic help you treat this problem in different ways.
First read this question and then read Bbum's answer. In addition then read my summary.
atomic
will ALWAYS guaranteeWait what?! Are multithreading and thread safety different?
Yes. Multithreading means: multiple threads can read a shared piece of data at the same time and we will not crash, yet it doesn't guarantee that you aren't reading from a non-autoreleased value. With thread safety, it's guaranteed that what you read is not auto-released. The reason that we don't make everything atomic by default is, because there is a performance cost and for most things don't really need thread safety. A few parts of our code need it and for those few parts we need to write our code in a thread safe way using locks, mutex or synchronization.
nonatomic
Overall they are different in 2 aspects:
Crashing or not because of having or not having autorelease pool.
Allowing to be read right in the middle of a 'not yet finished write or empty value' or not allowing and only allowing to read when the value is fully written.
The truth is that they use spin lock to implement atomic property. The code as below: