ios - What's the difference between the atomic and nonatomic attributes?


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?



Answers


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:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

In this case, thread A could be renaming the object by calling setFirstName: and then calling setLastName:. In the meantime, thread B may call fullName 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.




This is explained in Apple's documentation, but below are some examples of what is actually happening. Note that there is no "atomic" keyword, if you do not specify "nonatomic" then the property is atomic, but specifying "atomic" explicitly will result in an error.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

Now, the atomic variant is a bit more complicated:

//@property(retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName_ retain];
      [userName release];
      userName = userName_;
    }
}

Basically, the atomic version has to take a lock in order to guarantee thread safety, and also is bumping the ref count on the object (and the autorelease count to balance it) so that the object is guaranteed to exist for the caller, otherwise there is a potential race condition if another thread is setting the value, causing the ref count to drop to 0.

There are actually a large number of different variants of how these things work depending on whether the properties are scalar values or objects, and how retain, copy, readonly, nonatomic, etc interact. In general the property synthesizers just know how to do the "right thing" for all combinations.




Atomic

  • is the default behavior
  • will ensure the present process is completed by the CPU, before another process accesses the variable
  • is not fast, as it ensures the process is completed entirely

Non-Atomic

  • is NOT the default behavior
  • faster (for synthesized code, that is, for variables created using @property and @synthesize)
  • not thread-safe
  • may result in unexpected behavior, when two different process access the same variable at the same time



Why properties are always said to be made nonatomic in Objective C?

Declaring a property atomic makes compiler generate additional code that prevents concurrent access to the property. This additional code locks a semaphore, then gets or sets the property, and then unlock the semaphore. Compared to setting or getting a primitive value or a pointer, locking and unlocking a semaphore is expensive (although it is usually negligible if you consider the overall flow of your app).

Since most of your classes under iOS, especially the ones related to UI, will be used in a single-threaded environment, it is safe to drop atomic (i.e. write nonatomic, because properties are atomic by default): even though the operation is relatively inexpensive, you do not want to pay for things that you do not need.




see the difference between atomic and nonatomic in objective c

Atomic

Atomic is the default behaviour for a property; by not explicitly setting the above property as nonatomic, it will be atomic.

An atomic property adds a level of thread safety when getting or setting values. That is, the getter and setter for the property will always be fully completed regardless of what other threads are doing. The trade-off is that these properties will be a little slower to access than a nonatomic equivalent.

Non-Atomic

Nonatomic properties are not thread safe, and will return their properties directly. This will be faster than atomic properties, but obviously carries some risk if precautions aren’t made.




@property (strong) NSString *str;

Atomic is the default behaviour for a property; by not explicitly setting the above property as nonatomic, it will be atomic.

setter & getter for these Atomic property

-(NSString *) str{
@synchronized(self){
return str;
}}

-(void) setStr: (NSString *) newString {
@synchronized(self)  {
str = newString;
}}

An atomic property adds a level of thread safety when getting or setting values. That is, the getter and setter for the property will always be fully completed regardless of what other threads are doing. these properties will be a little slower to access than a nonatomic equivalent.

@property (strong,nonatomic) NSString *str;

Nonatomic properties are not thread safe, and will return their properties directly. This will be faster than atomic properties, but obviously carries some risk if precautions aren’t made.

setter & getter for these Nonatomic property

-(NSString *) str{
    return str;
    }}

-(void) setStr: (NSString *) newString{
str = newString;
}

So by looking on the setter & getter methods for both Atomic & nonatomic that nonatomic methods are very light weight.




What's the difference between 'atomic' and non-atomic?

Atomic properties are necessary in a reference counted multi threaded environment in order to stop objects from disappearing before a thread has a chance to retain them.

Consider the naive implementation of a get accessor:

@interface MyObject : NSObject 
{
    id myPropertyIVar;
}
-(id) myProperty;

@end

@implementation MyObject

-(id) myProperty
{
    return myPropertyIvar;
}

// other stuff

@end

This is all fine except that if you release the instance of MyObject before retaining the returned value from -myProperty the returned value may well be deallocated. For this reason, it is safer to implement -myProperty like this:

-(id) myProperty
{
    return [[myPropertyIvar retain] autorelease];
}

This is now completely safe in a single threaded environment.

Unfortunately, in a multithreaded environment there is a race condition. If the thread is interrupted at any time before the retain has incremented the retain count, either of the following will cause you to receive a garbage pointer:

  • the instance of MyObject is released and deallocated by another thread causing the ivar to be released and deallocated
  • myProperty is reassigned by another thread causing the old version to be released and deallocated

For this reason, all accesses to the property must be protected by a lock. The get accessor looks something like this.

-(id) myProperty
{
    // lock
    return [[myPropertyIvar retain] autorelease];
    // unlock
}

The set accessor is similarly protected and so is the release in -dealloc




The Apple docs explain all this very well. To learn about properties, including their atomicity, read this page.




Why should I ever use nonatomic in a property?

A short answer is performance. If you declare properties as atomic, the synthesized accessors will use locks to ensure that values are fully retrieved and set. If you don't need this, e.g., your application is single-threaded, you're incurring a performance penalty for those locks without getting a benefit.