Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
305 views
in Technique[技术] by (71.8m points)

objective c - Which is threadsafe atomic or non atomic?

I searched and found immutable are thread safe while mutable is not. This is fine. But i got misleading notes, blogs, answers about atomic vs non-atomic about thread safety, kindly give an explanation for the answer.

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 operation on different thread will be performed serially which means if one thread is executing 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.

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.

Yours comment on this will help us....

And my question is, "which is thread safe in cocoa, atomic or non-atomic?"

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For ObjC Properties -- Neither are thread safe.

Atomic is more resistant to threading errors. Overall, it is a curious default. The scenarios you would favor atomic for are very few. Atomic can increase the probability of correctness, but it's at too low a level be considered a substitute for a proper locking mechanism. Therefore, if you need thread safety, you still need some other synchronization primitive on top of the atomic reads/writes. If you don't need thread safety (e.g. the instance is immutable or intended to be run from the main thread only), atomic will add nothing.

Being resistant to threading errors is not a 'quality' -- it serves to mask real threading errors and make them more difficult to reproduce and detect.

Also note that mutable vs. immutable types do not actually guarantee threadsafety. 'Mutable' may be used in ObjC names to refer only to the interface -- the internals of an immutable instance may actually have internal mutable state. In short, you cannot assume that a type which has a mutable subclass is thread safe.


Question Expanded:

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 operation on different thread will be performed serially which means if one thread is executing setter or getter, then other threads will wait.

If all threads tried to read and/or write to the property at the same time, only one thread would have access at a time and the others would be blocked if the property were atomic. If the property were nonatomic, then they would all have unguarded read and write access to the variable at the same "time".

if another thread D calls [name release] simultaneously then this operation might produce a crash because there is no setter/getter call involved here.

Correct.

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.

Well, there's really a lot more to it. The common example is:

    @interface MONPerson : NSObject

    @property (copy) NSString * firstName;
    @property (copy) NSString * lastName;

    - (NSString *)fullName;

    @end

Atomic, or nonatomic, you will need a synchronization mechanism (e.g. lock) if one thread is reading from that instance and another is writing to it. You may end up with one MONPerson's firstName and another's lastName -- The object may have changed before the getter's return value is even returned to you, or this can happen:

Thread A:

p.firstName = @"Rob";

Thread B:

p.firstName = @"Robert";

Thread A:

label.string = p.firstName; // << uh, oh -- will be Robert

If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result.

Right - initial symptoms can be reference count imbalances (leak, over-release).

In case of atomic, Either one of A, B or C will execute first but D can still execute in parallel. Kindly comment on this....

Correct. But if you look at the example above -- atomic alone is rarely a suitable replacement for a lock. It would have to look like this instead:

Thread A:

[p lock]; // << wait for it… … … …
// Thread B now cannot access p
p.firstName = @"Rob";
NSString fullName = p.fullName;
[p unlock];
// Thread B can now access p
label.string = fullName;

Thread B:

[p lock]; // << wait for it… … … …
// Thread A now cannot access p
…
[p unlock];

Atomic accessors can average over twenty times slower than nonatomic accesses. As well, if your class needs to be threadsafe and has mutable state, you will likely end up using a lock when it operates in a concurrent scenario. Proper locking provides the all guarantees you need -- atomic accessors are redundant in that scenario, using atomics would only add CPU time. Another good thing about the regular lock is that you have all the granularity you need -- although it is often heavier than the spin lock used for atomics, you will typically need fewer acquires so it ends up being very fast if you use regular locks correctly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...