What Does the Property "Nonatomic" Mean

What does the property Nonatomic mean?

Take a look at the Apple Docs.

Basically, if you say nonatomic, and you generate the accessors using @synthesize, then if multiple threads try to change/read the property at once, badness can happen. You can get partially-written values or over-released/retained objects, which can easily lead to crashes. (This is potentially a lot faster than an atomic accessor, though.)

If you use the default (which is atomic; there used to be no keyword for this, but there is now), then the @synthesized methods use an object-level lock to ensure that multiple reads/writes to a single property are serialized. As the Apple docs point out, this doesn't mean the whole object is thread-safe, but the individual property reads/writes are.

Of course, if you implement your own accessors rather than using @synthesize, I think these declarations do nothing except express your intent as to whether the property is implemented in a threadsafe manner.

What is the meaning of nonatomic and retain in a property declaration

Properties are used in iOS to replace the getter and setter methods which we normally write.

Your line of code:

@property(nonatomic, retain) UIView *singleTapView;

means that you are writing the getter and setter methods for your UIView.

And it'll automatically retain or increment the retain count of your UIView whenever you use it anywhere in your code.

However, when you use:

@property(nonatomic, assign) UIView *singleTapView;

and then use your UIView, its retain count won't increase. This means that it will not retain your UIView.

And "copy" is just used to give the value of your current object to a new object.

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

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.

Does `nonatomic` makes sense in a `readonly` declared property (including class property)?

The atomic/nonatomic modifiers have no effect in your case, for multiple reasons.

The main reason is that atomicity keywords affect only generated code (i.e. synthesized accessor methods). When you declare a @property in your interface and then implement it with a method (or method pair) in your implementation, the compiler isn't generating code, so your atomicity keyword is ignored.

There are a few ways to get to this situation, and you're triggering a couple of them:

  • First, you have a class property. The compiler can't synthesize accessors or storage for class properties — which means no code generation, so atomicity doesn't apply.

  • Second, in most common uses of readonly properties, the @property declaration is backed by a manually implemented getter method — which means there's no code generation and thus atomicity doesn't apply.

    (Note you can also have instance properties declared as readonly in a public interface and synthesized due to a private readwrite redeclaration in your implementation. In that case, not only does atomicity apply, you have to make the atomicity keywords match between your public and private declarations. You can also synthesize just a getter and work directly with the backing ivar in your implementation.)

Because specifying either atomic or nonatomic for this property does nothing either way, you're free to just leave atomicity keywords out of your declaration entirely. (The compiler will assume atomic, but as noted that assumption has no effect.)

Do I have to use nonatomic property in objective-c ios programing?

If you delete nonatomic from property then by default all your properties will be 'atomic'.
If there are a lot of 'atomic' properties without purpose then it will slow up your app, because at compile time atomic properties generate a complex code and every time you use that property that code will be executed.

Atomic property of a nonatomic primitive vs. nonatomic property of an atomic primitive?

I'm not sure there is a definitive answer to your question, but as no other answers exist at the time of writing I'll offer the following in the hope it helps.

Declared properties, along with the nonatomic qualifier (by default properties were atomic and atomic did not exist), were introduced in Objective-C 2.0 circa 2009. _Atomic() comes from C11, circa 2011.

So we have two independent language developments addressing atomicity.

Objective-C is not rigorously defined, the last "specification" of the whole languages dates from 2009 despite extensions since then, and I know of no specification that discusses how the atomic features of C and the atomic properties of Objective-C interact. So as with many Objective-C questions it is down to what the compilers do.

With the current Xcode 8.x compilers targeting Intel appear to produce code which respects atomicity, up to at least 128 bits (the limits of testing for this answer), for all combinations of atomic and _Atomic() – though specifying both is somewhat redundant. Code produced for atomic is more likely to involve spin locks and of course involve function calls; while _Atomic() is more likely to use cpu exchange instructions and be compiled inline.

So should we prefer the latter? [_Atomic()]

If you intend to use direct access to the backing variable, and I'll skip any discussion of the merits or otherwise of doing that, then probably.

If you don't intend to access the backing variable directly then using Atomic() might exchange a spin lock call for a single cpu instruction, each with its own impacts, so any preference is down to how you weigh those.

In short: YMMV, the above applies to Intel, Xcode 8.x, etc. Hope it was some help, interesting question.

Objective-C declared @property attributes (nonatomic, copy, strong, weak)

Nonatomic

Nonatomic will not generate threadsafe routines thru @synthesize accessors. atomic will generate threadsafe accessors so atomic variables are threadsafe (can be accessed from multiple threads without botching of data)

Copy

copy is required when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.

Assign

Assign is somewhat the opposite to copy. When calling the getter of an assign property, it returns a reference to the actual data. Typically you use this attribute when you have a property of primitive type (float, int, BOOL...)

Retain

retain is required when the attribute is a pointer to a reference counted object that was allocated on the heap. Allocation should look something like:

NSObject* obj = [[NSObject alloc] init]; // ref counted var

The setter generated by @synthesize will add a reference count to the object when it is copied so the underlying object is not autodestroyed if the original copy goes out of scope.

You will need to release the object when you are finished with it. @propertys using retain will increase the reference count and occupy memory in the autorelease pool.

Strong

strong is a replacement for the retain attribute, as part of Objective-C Automated Reference Counting (ARC). In non-ARC code it's just a synonym for retain.

This is a good website to learn about strong and weak for iOS 5.
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1

Weak

weak is similar to strong except that it won't increase the reference count by 1. It does not become an owner of that object but just holds a reference to it. If the object's reference count drops to 0, even though you may still be pointing to it here, it will be deallocated from memory.

The above link contain both Good information regarding Weak and Strong.

what is diff. b/w @property (nonatomic,assign) and @property (nonatomic,retain)

You should assign (= no change in retain count) delegates because you want to avoid "retain loops" (can't think of a better word)

Take a UITableView and a UIViewController.

When you add the UITableView to your viewController you retain it. Then you assign a delegate and a datasource (which is a delegate too) to your UITableView. Usually this is your viewController.

If the tableview would retain the datasource (your viewController) there would be a "retain loop"

viewontroller retains tableview.

tableview retains viewcontroller

The viewcontrollers dealloc (where you release the tableview) would never be called because tableview would never release your viewcontroller. And the other way around.

And because of this neither would get deallocated. That's why UITableView only assigns the datasource and the delegate. And you should do the same in your classes.

Evidence of atomic / nonatomic in Objective-C

Having non-atomic properties makes the possibility of partial writes possible, but by no means certain.

In your Person class the only way you are setting first and last names is in the init method, and then you set the first name and then the last name immediately after. Setting the first name and last name will occur VERY close to each other, with little chance for another thread to mess things up between operations.

Furthermore, you create your Person objects in the main thread, before you running concurrent operations. By the time your current code runs, the objects already exist and you no longer change their name values, so there's no chance of a race condition or a partial write with name values. You are simply changing self.p between 2 objects that don't change once they are created.

That said, what IS unpredictable about your code is what person object will be in self.p at any instant. You should see the values displayed alternate between Bob Sponge and Jack Frost unpredictably.

A better test would be something like this:

(Assume each TestObject's x1 and x2 values should always be kept the same.)

@interface TestObject : NSObject
@property (nonatomic, assign) int x1;
@property (nonatomic, assign) int x2;
@end

@interface AppDelegate
@property (nonatomic, strong) TestObject *thing1;
@property (nonatomic, strong) TestObject *thing2;
@property (nonatomic, strong) NSTimer *aTimer;
@property (nonatomic, strong) NSTimer *secondTimer;
@end

And then code like this:

#include <stdlib.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);

self.thing1 = [[TestObject alloc] init];
self.thing2 = [[TestObject alloc] init];

dispatch_async(queue1, ^
{
for (int x = 0; x < 100; x++)
{
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
int thing1Val = arc4random_uniform(10000);
int thing2Val = arc4random_uniform(10000);
_thing1.x1 = thing1Val;
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
_thing2.x1 = thing2Val;
_thing1.x2 = thing1Val; //thing1's x1 and x2 should now match
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
_thing2.x2 = thing2Val; //And now thing2's x1 and x2 should also both match
}
});

//Do the same thing on queue2
dispatch_async(queue2, ^
{
for (int x = 0; x < 100; x++)
{
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
int thing1Val = arc4random_uniform(10000);
int thing2Val = arc4random_uniform(10000);
_thing1.x1 = thing1Val;
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
_thing2.x1 = thing2Val;
_thing1.x2 = thing1Val; //thing1's x1 and x2 should now match
usleep(arc4random_uniform(50000)); //sleep for 0 to 50k microseconds
_thing2.x2 = thing2Val; //And now thing2's x1 and x2 should also both match
}
});

//Log the values in thing1 and thing2 every .1 second
self.aTimer = [NSTimer scheduledTimerWithTimeInterval:.1
target:self
selector:@selector(logThings:)
userInfo:nil
repeats:YES];

//After 5 seconds, kill the timer.
self.secondTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(stopRepeatingTimer:)
userInfo:nil
repeats:NO];
return YES;
}

- (void)stopRepeatingTimer:(NSTimer *)timer
{
[self.aTimer invalidate];
}

- (void)logThings:(NSTimer *)timer
{
NSString *equalString;
if (_thing1.x1 == _thing1.x2)
{
equalString = @"equal";
}
else
{
equalString = @"not equal";
}
NSLog(@"%@ : thing1.x1 = %d, thing1.x2 = %d",
equalString,
_thing1.x1,
_thing1.x2);

if (_thing2.x1 == _thing2.x2)
{
equalString = @"equal";
}
else
{
equalString = @"not equal";
}
NSLog(@"%@ : thing2.x1 = %d, thing2.x2 = %d",
equalString,
_thing2.x1,
_thing2.x2);
}

In the code above, each queue creates a series of random values, and sets both the x1 and x2 properties of a couple of objects to those random values in a repeating loop. It delays for a small random interval between setting the x1 and x2 property of each object. That delay simulates a background task taking some amount of time to finish work that should be atomic. It also introduces a window where another thread could change the second value before the current thread is able to set the second value.

If you run the code above you will almost certainly find that the x1 and x2 values of thing1 and thing2 are sometimes different.

The code above would not be helped by atomic properties. You would need to assert a lock of some sort between setting the x1 and x2 property of each object (perhaps using the @synchronized directive).

(Note that I banged the code above together in the forum editor. I haven't tried to compile it, much less debug it. There are doubtless a few typos.)

(Note 2, to the person who edited my code: Code formatting is a matter of style and personal taste. I use a variation on "Allman indentation." I appreciate the typos corrections, but I despise K&R style indentation. Don't impose your style on my code.



Related Topics



Leave a reply



Submit