[Ios] What's the difference between the atomic and nonatomic attributes?


Answers

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.

Question

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?




Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

Example:

.h class

@interface ExampleClass : NSObject
   @property (nonatomic, retain) NSString *name;
@end

.m class

@implementation ExampleClass
   @synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@“Tiger”];

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

Example :

@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads. For this reason, it’s faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

copy: If you use copy, you can't use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

@property (copy) NSString *name;

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"];

readonly: If you don't want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readwrite: is the default behaviour. You don't need to specify readwrite attribute explicitly.

@property (readwrite) NSString *name;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

@property (assign) NSInteger year;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;




Atomic :

Atomic guarantees that access to the property will be performed in an atomic manner. E.g. it always return a fully initialised objects, any get/set of a property on one thread must complete before another can access it.

If you imagine the following function occurring on two threads at once you can see why the results would not be pretty.

-(void) setName:(NSString*)string
{
  if (name)
  {
    [name release]; 
    // what happens if the second thread jumps in now !?
    // name may be deleted, but our 'name' variable is still set!
    name = nil;
  }

  ...
}

Pros : Return of fully initialised objects each time makes it best choice in case of multi-threading.

Cons : Performance hit, makes execution a little slower

Non-Atomic :

Unlike Atomic, it doesn't ensure fully initialised object return each time.

Pros : Extremely fast execution.

Cons : Chances of garbage value in case of multi-threading.




Let's take an example:-

@property (atomic, strong) NSString *atomicProperty;
@property (nonatomic, strong) NSString *nonAtomicProperty;

Atomic Properties:-

1) Defining a property as atomic will guarantee that a valid value will be returned. Notice that valid does not always mean correct (more on that in the next section of this post)

2) Atomic properties suffer from the minor performance hit due to locking and unlocking before and after setting/getting a value.

3) Atomic is the default behavior for properties — this is what you get if you don’t specify anything.

Non-Atomic Properties:-

1) Nonatomic properties have no guarantee regarding the returned value.

2) It can be the correct value, a partially written value or even some garbage value.

3) As most things that are not safe — this comes with an enhanced speed of accessing these properties.

Let's see how does the Objective-C runtime do this programmatically?

Let’s look at the “set value” method for the Objective-C runtime.

Notice how nonatomic properties are directly setting the value of the property while an atomic property is using locks to protect the set operation




Atomic = thread safety

Non-atomic = No thread safety

Thread safety:

Instance variables are thread-safe if they behave correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.

In our context:

If a thread changes the value of the instance the changed value is available to all the threads, and only one thread can change the value at a time.

Where to use atomic:

if the instance variable is gonna be accessed in a multithreaded environment.

Implication of atomic:

Not as fast as nonatomic because nonatomic doesn't require any watchdog work on that from runtime .

Where to use nonatomic:

If the instance variable is not gonna be changed by multiple threads you can use it. It improves the performance.




To simplify the entire confusion let us understand mutex lock.Mutex lock as per the name locks the mutability of the object.So if the object is accessed by a class no other class can access the same object.In iOS @sychronise also provide the mutex lock.Now it serve in FIFO mode and ensures the flow is not affected by two classes sharing the same instance.However if the task is on main thread avoid accessing object using atomic properties as it may hold your UI and degrade the performance




The default is atomic, this means it does cost you performance whenever you use the property, but it is thread safe. What Objective-C does, is set a lock, so only the actual thread may access the variable, as long as the setter/getter is executed.

Example with MRC of a property with an ivar _internal:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

So these last two are the same:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic

On the other hand does nonatomic add nothing to your code. So it is only thread safe if you code security mechanism yourself.

@property(nonatomic, retain) UITextField *userName;

The keywords doesn't have to be written as first property attribute at all.

Don't forget, this doesn't mean that the property as a whole is thread-safe. Only the method call of the setter/getter is. But if you use a setter and after that a getter at the same time with 2 different threads, it could be broken too!




If you are using atomic, it means the thread will be safe and read-only. If you are using nonatomic, it means the multiple threads access the variable and is thread unsafe, but it is executed fast, done a read and write operations; this is a dynamic type.




Atomic is thread safe, it is slow and it well-assures (not guaranteed) that only the locked value is provided no matter how many threads are attempting access over the same zone. When using atomic, a piece of code written inside this function becomes the part of the critical section, to which only one thread can execute at a time.

It only assures the thread safety; it does not guarantee that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car won't meet an accident. However, probability remains the slightest.

Atomic - it can't be broken down, so the result is expected. With nonatomic - when another thread access the memory zone it can modify it, so the result is unexpected.

Code Talk :

Atomic make getter and setter of the property thread safe. for example if u have written :

self.myProperty = value;

is thread safe.

[myArray addObject:@"Abc"] 

is NOT thread safe.




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 atomic property ensures to retain a fully initialised value irrespective of how many threads are doing getter & setter on it.

The nonatomic property specifies that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.




After reading so many articles, Stack Overflow posts and making demo applications to check variable property attributes, I decided to put all the attributes information together:

  1. atomic // Default
  2. nonatomic
  3. strong = retain // Default
  4. weak = unsafe_unretained
  5. retain
  6. assign // Default
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Default

In the article Variable property attributes or modifiers in iOS you can find all the above-mentioned attributes, and that will definitely help you.

  1. atomic

    • atomic means only one thread access the variable (static type).
    • atomic is thread safe.
    • But it is slow in performance
    • atomic is the default behavior
    • Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to ensure that another thread doesn't interfere with the correct setting/getting of the value.
    • It is not actually a keyword.

    Example:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic means multiple thread access the variable (dynamic type).
    • nonatomic is thread-unsafe.
    • But it is fast in performance
    • nonatomic is NOT default behavior. We need to add the nonatomic keyword in the property attribute.
    • It may result in unexpected behavior, when two different process (threads) access the same variable at the same time.

    Example:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    



If you are using your property in multi-threaded code then you would be able to see the difference between nonatomic and atomic attributes. Nonatomic is faster than atomic and atomic is thread-safe, not nonatomic.

Vijayendra Tripathi has already given an example for a multi-threaded environment.