6

In Android, I could safely access and modify primitive types from different threads. I used this to share data between my OpenGL draw loop and user settings that were modified in the main thread Android UI. By storing each setting in a primitive type and making each independent of the others' values, it was thread-safe to modify all these variables without using locks or the synchronize keyword.

Is this also true in Objective-C? I read that placing atomic on a variable essentially causes the synthesized getter and setter to use locks, similar to using synchronized methods in Java. And I've read that the reason for this is so an object does not get partially modified while it's being read by another thread.

But are primitive types safe from being partially modified, as they are in Java? If that is the case, it seems like I could use my same old paradigm from Java for sharing data between threads. But then the atomic keyword would be pointless for a primitive, correct?

I also read that a more robust and faster solution than using atomic variables is to copy objects before using them if they are accessed from multiple threads. But I'm not sure how that could be accomplished. Couldn't a nonatomic object get modified while it's in the process of being copied, thereby corrupting the copy?

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • 1
    why not declaring primitive type with atomic to ensure thread safety? – John Sep 07 '13 at 00:21
  • possible duplicate of [Atomic vs nonatomic properties](http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties) – bbum Sep 07 '13 at 02:10
  • @user1256663 I've heard they're very slow, and I'm writing an OpenGL app. Framerate concerns. – Tenfour04 Sep 07 '13 at 03:37

3 Answers3

6

Primitive types aren't guaranteed to be safe from being partially modified because modifications to primitive types aren't guaranteed to be atomic in C and Objective-C inherits from there. C's only guarantees concern sequence points and there's no requirement that the processing between two sequence points be atomic — a rule of thumb is that each full expression is a sequence point.

In practice, modifying primitives is often a two-step process; the modification is made in a register and then written out to memory. It's very unlikely that the write itself will not be atomic but there's also no guarantee of when it will occur versus the modification. Even with the volatile qualification, the only guarantees provided are in terms of sequence points.

Apple exposes some C functions for atomic actions via OSAtomic.h that map directly to the specialised atomic instructions that CPUs offer for the implementation of concurrency mechanisms. It's possible you could use one of those more directly than via a heavy-handed mutex.

Common patterns in Objective-C are:

  • immutable objects and functional transformations — there are memory management reasons as well but that's partly why NSString, NSArray, etc, are specifically distinct from NSMutableString, NSMutableArray, etc;
  • serial dispatch queues, which can be combined with copy-modify-replace by copying on the queue, going off somewhere else to modify, then jumping back onto the queue to replace;
  • such @synchronizeds, NSConditionLocks or other explicit synchronisation mechanisms as are appropriate.

The main thread itself is a serial dispatch queue, which is why you can ignore the issue of concurrency entirely if you restrict yourself to it.

Tommy
  • 99,986
  • 12
  • 185
  • 204
3

Atomic synthesized @properties are immune to concurrent partial updates. The accessor methods will use a lock if necessary on that architecture.

In general, primitive types in C are not necessarily safe with respect to concurrent partial updates.

Greg Parker
  • 7,972
  • 2
  • 24
  • 21
-2

I don't believe you can partially modify a primitive type, that's part of what makes them primitive. You either modify it or you don't. In that sense, I would say that they are thread safe.

You are correct when you say that the atomic keyword would be pointless for a primitive type.

Someone already took a stab at this here: Objective-c properties for primitive types

Community
  • 1
  • 1
Simon Germain
  • 6,834
  • 1
  • 27
  • 42
  • 1
    You can't "see" a partially-modified primitive type *on most architectures*, so long as the primitive is cache-aligned. – Hot Licks Sep 07 '13 at 00:26
  • 1
    Depends on the primitive and on the architecture. For example, some ARM architectures use eight-byte doubles but formally only promise atomicity for four-byte loads and stores. – Greg Parker Sep 07 '13 at 01:47