Skip to main content

Deep Diving Objective-C Properties (Part 2)

Previous post of properties explained about the lifetime qualifiers. Today post will have exciting stuff about the other qualifier and some concepts about where to used these qualifier.

Threads and Properties:


Suppose you are working in multithreaded environment and two thread want to access the same property at same time. Thread A want to write and thread B is in middle of reading the property name. 
What happen which value thread B will get. ?

There are two qualifier which decide the behaviour in such condition.
1)  atomic (Default)
2) nonatomic

Atomic:


1) Default behaviour.
2) Ensure that one thread will access property or method at a time. (Inconsistency will be not there as atomicity). Thread B will get autorelease value always in the above case.
3) Does not ensure the thread safety of instance variable. Any other thread can access the instance variable bind to property. So instance variable in not thread safe only setter and getter is thread safe.
4) Performance wise it is slow. For thread safety it need to lock the flow so that other method cannot access the methods at a same time. It used similar mechanism as we used "synchronized block". We will look in more detail of method definition in case of atomic.

Suppose you are standing in queue for apple product as given below:


Atomic properties are like you are entering or accessing the apple store one by one using doors. So doors in our case are properties. Threads are accessing the instance variable using doors (Properties) one by one.

But what happen if somebody destroy or collapses the store nobody can enter the store.   
In similar manner if somebody release the instance variable while other thread accessing the instance variable. In that case the release will happen and application would be crashed Bad Excess :( . 

Example:
@property (retainNSString* name;
@property (atomic, retainNSString* city;


Nonatomic:

1) Not a thread safety for accessors. So in above case the result will be unpredictable. Thread B can get the autorelease value or the value set by Thread A. It is purely luck here and luck decided by the run time environment of objective -c . 
2) Faster performance in multithreaded environment. Even in a single thread case the performance is higher side with nonatomic. When your application is not multithreaded you  should use nonatomic.

Let us understand the case of non atomic and multithreaded environment:





Problem : In a room there is bulb with switch and there are 10 people standing outside the room. They will enter in the room and change the status of button (If a bulb is on the off it else on it).  
If people make a queue you can predict the behaviour of bulb at any time. If people just rush to room like below case:


Then prediction is impossible (Obviously every one can predict the behaviour in end by counting the number of person ;).
Similar is the case for non atomic. If number of threads accessing the same property at particular time then prediction is impossible. What value thread get when using the getter of the variable.

Example:

@property (nonatomic, retain)NSString* name;

So That all about Thread and Properties.


Performance Test:

Atomic and NonAtomic:

I tested the atomic and non atomic case by taking the reference from the blog:
I declare two properties  in Person class

Person.h


@interface Person : NSObject

@property (strong, nonatomic) NSString* name;
@property (strong, atomic) NSString*    city;

@end

Person.m

@implementation Person

@end

Then in my controller i write the following method:

- (void) testPerformanceResult{
    _person.name = @"Objective - C";
    _person.city = @"Apple";
    
    CFTimeInterval startNonAtomcTime = CACurrentMediaTime();
    
    for (int i=0; i<1000; i++) {
       [_person name];
    }
    
    CFTimeInterval endNonAtomicTime = CACurrentMediaTime();
    
    NSLog(@"1000 nonatomic accesses, t = %.9f seconds", endNonAtomicTime-startNonAtomcTime);
    
    CFTimeInterval startAtomicTime = CACurrentMediaTime();
    for (int i=0; i<1000; i++) {
       [_person city];
    }
    
    CFTimeInterval endAtomicTime = CACurrentMediaTime();
    
    NSLog(@"1000 atomic accesses, t = %.9f seconds", endAtomicTime-startAtomicTime);
}

For me atomic property always taking more time then non atomic. For 1000 run following is the result:

2015-01-12 12:54:59.119 Hello world[1546:47159] 1000 nonatomic accesses, t = 0.000019835 seconds
2015-01-12 12:54:59.120 Hello world[1546:47159] 1000 atomic accesses, t = 0.000050940 seconds

You can try by your self in your code :). As we can see there is not much time difference but until your application is not multithreaded you should use nonatomic. 



Permission Qualifier:

There are two qualifiers, which defined the access permission for properties. Whether you can write the value in properties or it is just read only for you.
1) readwrite (Default)
2) readonly


Readwrite:

1) Default Behaviour.
2) When you synthesize the property both setter and getter will be created.

Example:
@property (atomic,retain, readwrite)NSString*     city;

ReadOnly:

1) When you synthesize the property only getter will be created by the compiler.
@property (readonly)NSUInteger    SSNNumber;

Let us cover the important point about the properties which you should take care of it.

Important Point About Properties:

1) You cannot use new as prefix for any property name or you can change the getter name of the properties.

@property (nonatomic, retain, getter=city)NSString* newCity;

2) Default qualifier for properties are Atomic and strong in ARC. In case of primitive type the default qualifier is Atomic and Assign.

@property NSString*     city; //atomic and strong
@property NSUInteger    SSNNumber; //atomic and assign

3) You can use permission qualifier to make a property private. 

Person.h


@interface Person : NSObject

@property (atomic,retain, readonly)NSString*     city;


@end

Person.m

@interface Person ()

@property (atomic,retain, readwrite)NSString*     city;

@end

@implementation Person

@end


Done:). Property is readonly for the other object accessing the person attributes.
Next Post will cover the Block programming with properties.

Comments

Popular posts from this blog

Asynchronous Request with NSOperationQueue

Today post is about how to run a asynchronous task in NSOperationQueue.  Generally we do not run a Asynchronous task in NSOperationQueue. It is also not recommended for any programmer to do that. This post is only for learning purpose what will happen if we schedule a asynchronous task in a queue and how can we complete that task:). So let us move to the learning: NSOperationQueue: In iOS NSOperationQueue is a class, which provide a way to perform operation concurrently. We also have others way to perform concurrent operation: 1) GCD 2) NSThread 3) pThread NSOperationQueue is a wrapper on GCD, which provides a very convenient way to execute operation concurrently. To create a Queue for Operation you have to simply allocate a object of the class: NSOperationQueue * opertionQueue = [[ NSOperationQueue alloc ] init ]; For this post let suppose you are making a queue to handle all Http request in your application. So i want to create a queue in Handl...

Shake Effect in iOS

Animation Animation always capture the user attention. We can use animation to update things on the screen.  For developer also animations fascinated things to learn and implement. Today we will try shake effect with Various  API. CABasicAnimation: Here we animate view's frame y coordinate from one position to another position. It is simple example of changing the position with respect to time. CABasic Animation is deal with the single keyframe.                                        y(t) = y 0 + t*d(y) You can use CABasic Animation if you have to play with single value. You need to move object from  one position to another without any intermediate steps. CABasicAnimation * shakeAnimation = [CABasicAnimation animationWithKeyPath: @ "position" ]; shakeAnimation . duration = 0.05 ; shakeAnimation . autoreverses = YES; shakeAnimation . repe...

NSThread with Asynchronous Request

NSThread: It is class used in Cocoa framework to create a thread.You have to specify a target and selector to create a new thread in objective c. So the selector or method is main entry point of your thread.  Detail: What happen once the thread execute all the code in the method (Thread main routine)? Thread is terminated after execute all the code in the entry(its main routine) routine. So how we can run an asynchronous request on NSThread ? What is Async request? It is non blocking request which permit the application to do other task side by side as request is in continue. So it enhance parallelism in the application. Now question is how we can prepare a asynchronous request in iOS: - ( void ) startAsyncRequestWithUrl:( NSString *)urlString{     assert (urlString != nil && urlString. length > 0 );     NSURL * url = [[ NSURL alloc ] initWithString :urlString];     NSURLRequest * urlRequest = [[ NSURLReq...