user3460006
user3460006

Reputation: 122

Why atomic is not sufficient in thread safety for complex objects

atomic keyword is applied to properties of a class, for thread safety.

Usage of atomic is thread safe for primitive data types but not the complex objects (modal objects). Why ?

Thanks in advance for the kind reply!

Update

If Person is a Class having properties name, age, address.

Consider

@property(atomic, strong) Person *adam;

How far is the object adam thread safe ?

Upvotes: 2

Views: 119

Answers (2)

Sulevus
Sulevus

Reputation: 659

The difference stems from the fact that an object comes with its own methods and behaviour, which could cause changes to the object outside of its setter and getter.

Atomic keyword provides thread synchronisation only between the setter and getter that the compiler synthesizes.

This is generally sufficient to provide thread safety to a primitive property, as its underlying ivar is only accessed via its setter and getter.

However, for an object property this would only provide thread safety for the pointer to the object. The setter and getter would be synchronized themselves, but some other method of that object may be modifying it from a different thread and the property will not be thread safe overall. If you want to make it safe you'll have to implement synchronisation with all methods that have the potential to modify the object.

For example, the following immutable string should be thread safe because it is only modified via accessors

@property (atomic, strong) NSString * immutableString;

While the following mutable one will not be thread safe

@property (atomic, strong) NSMutabeString * mutableString;

Upvotes: 2

bbum
bbum

Reputation: 162712

This is really a dupe of What's the difference between the atomic and nonatomic attributes? even prior to the edit, though it wasn't obvious.

Since that answer is referred to often, I added the following to underscore that thread safety is really all about having some kind of a transactional model where the reads and writes are controlled such that the system is in a known, integral, state when a read or write happens.

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.

Upvotes: 2

Related Questions