3

I've already seen this question:
What's the difference between the atomic and nonatomic attributes?

I understand that @atomic does not guarantee thread safe, and I have to use other mechanisms (e.g. @synchronized) to realize that. Based on that, I don't still know EXACTLY when to use @atomic attribute. I'd like to know USE CASE of using @atomic alone.

Community
  • 1
  • 1
Toru
  • 353
  • 3
  • 15

3 Answers3

5

The typical use-case for atomic properties is when dealing with a primitive data type across multiple threads. For example, let's say you have some background thread doing some processing and you have some BOOL state property, e.g. isProcessComplete and your main thread wants to check to see if the background process is complete:

if (self.isProcessComplete) {
    // Do something
}

In this case, declaring this property as atomic allows us to use/update this property across multiple threads without any more complicated synchronization mechanism because:

  • we're dealing with a scalar, primitive data type, e.g. BOOL;
  • we declared it to be atomic; and
  • we're using the accessor method (e.g. self.) rather than accessing the ivar directly.

When dealing with objects or other more complicated situations, atomic generally is insufficient. As you point out, in practice, atomic, alone, is rarely sufficient to achieve thread safety, which is why we don't use it very often. But for simple, stand-alone, primitive data types, atomic can be an easy way to ensure safe access across multiple threads.

Rob
  • 371,891
  • 67
  • 713
  • 902
  • Does "fundamental data type" means "primitive" data types? – Toru Feb 28 '17 at 14:52
  • I mean scalar C data types, those primitive data types that consist of a single value or enums using one of those types. I mean to exclude compound or reference types such as objects, C arrays, and C structs. – Rob Feb 28 '17 at 16:26
1

@atomic will guarantee You, that the value, that You will receive will not be gibberish. A possible situation is to read a given value from one thread and to set its value from another. Then the @atomic keyword will ensure that You receive a whole value. Important thing to now is that the value that You get is not guaranteed to be the one that has been set most recently.

The second part of the Your question, about the use case is purely circumstantial, depending on the implementation the intentions. For example if You have some kind of time based update on a list every second or so, You could use atomic to ensure that You will get whole values, and the timer that updates Your list can ensure that You will have the latest data on screen or under the hood in some implicit logic.

EDIT: After a remark from @Rob I saw the need of paraphrasing the last part of my answer. In most cases atomic is not enough to get the job done. And there is a need of a better solution, like @synchronized.

Georgi Boyadzhiev
  • 1,301
  • 1
  • 11
  • 17
  • 6
    Just to clarify, the "the value ... will not be gibberish" is meaningful if dealing with a fundamental data type, but if dealing with an object, all it means is that the pointer to the object is not gibberish, but makes no assurances about the state of the object itself. If the object is mutable, then `atomic` provides little benefit. – Rob Feb 20 '17 at 16:27
  • 1
    My point was that `atomic` is not enough in most cases and You have to use some other way, but I totally agree with You, I will edit the answer. – Georgi Boyadzhiev Feb 20 '17 at 19:20
0

atomic guarantees that competing threads will get/set whole values, whether you're setting a primitive type or a pointer to an object. With nonatomic access, it's possible to get a torn read or write, especially if you're dealing with 64-bit values.

atomic also guarantees that an object pointer won't be garbage when you retrieve it: https://github.com/opensource-apple/objc4/blob/master/runtime/objc-accessors.mm#L58-L61.

That being said, if you're pointing to a mutable object, atomic won't offer you any guarantees about the object's state.

atomic is appropriate if you're dealing with:

  • Immutable objects
  • Primitives (like int, char, float)

atomic is inappropriate if:

  • The object or any of its descendant properties are mutable

If you need thread safety for a primitive value or immutable object, this is one of the fastest ways to guard against torn reads/writes that you can find.

mrgrieves
  • 477
  • 4
  • 18