Brynjar
Brynjar

Reputation: 1262

Can a bool var be safely accessed across threads?

This question pertains to Obj-C as the code is Obj-C, but I'd like to understand the difference (if any) in Swift too.

The golden rule in iOS that you shouldn't access an object across threads without using dispatch apis (or other) because this can lead to race conditions and other 'bad things'..

Is it safe however, to access a bool var from multiple threads? Since a bool var can only have one of two states, does that mean the following is always safe:

@property(nonatomic) BOOL processing;

-(void)callbackWithData(NSData *)data {
  if (_processing) {
    return;
  }
  // set from a background thread here
  _processing = YES;
  NSString *res = [self doSomeWorkThatReturnsString:data];

  dispatch_async(dispatch_get_main_queue(), ^{
    _someOtherCallback(res)
    // set from the main thread here
    _processing = NO;
  });
}

callbackWithData gets called 1 or more times, sometimes in quick succession, on a background thread(s). Thus the _processing check to prevent the _someOtherCallback block from being called multiple times.

Maybe changing the property definition to atomic and using the synthesized getter/setter would be safer, but the question about direct access to the bool var still stands.

EDIT: To be clear, the atomic thing is a side question. My question is about where or not the code as shown is safe, or might it somehow produce memory corruption or a race condition/deadlock/other

Upvotes: 2

Views: 679

Answers (1)

Andreas Oetjen
Andreas Oetjen

Reputation: 10199

From my knowledge, atomic properties will generate accessor code that locks the getter versus the setter call. This is only important for retain (and maybe copy) properties, since all others will just simply assign/return a value without prior checking. They won't help you in a more complex scenario, like the one you depicted in your code, when you first check the value and then do something depending on it.

Especially, if your callbackWithData is called by mutiple threads, it might evaluate _processing and see false, but and direcly after this, another thread my set _processing to true. No atomic could have helped you here.

If this might be a problem, you ought to use @synchronized(...) or some NSLock in your callbackWithData to lock the complete / most important parts of your method.

Upvotes: 1

Related Questions