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.
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.
1) Default behaviour.
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.
2015-01-12 12:54:59.119 Hello world[1546:47159] 1000 nonatomic accesses, t = 0.000019835 seconds
Done:). Property is readonly for the other object accessing the person attributes.
Next Post will cover the Block programming with properties.
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.
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:
Example:
@property (retain) NSString* name;
@property (atomic, retain) NSString* 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;
@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
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
Post a Comment