using @synchronize to solve Mutual Exclusion

ref – http://stackoverflow.com/questions/28005734/making-a-class-thread-safe-in-ios

mutual exclusion refers to the requirement of ensuring that no two concurrent processes[a] are in their critical section at the same time; it is a basic requirement in concurrency control, to prevent race conditions.

A race condition or race hazard is the behavior of an electronic, software or other system where the output is dependent on the sequence or timing of other uncontrollable events. It becomes a bug when events do not happen in the order the programmer intended. The term originates with the idea of two signals racing each other to influence the output first.

Example using @synchronized:

member variables

method definitions

applicationDidFinishLaunch

result:
2015-04-05 11:30:38.080 YonoApp[336:27030] incrementing player A gems
……
2015-04-05 11:30:38.084 YonoApp[336:27030] incrementing player A gems
2015-04-05 11:30:38.084 YonoApp[336:27030] decrementing player B gems
….
2015-04-05 11:30:38.091 YonoApp[336:27030] decrementing player B gems
2015-04-05 11:30:38.091 YonoApp[336:27030] transferToPlayerA – player A now has 120 gems
2015-04-05 11:30:38.091 YonoApp[336:27030] transferToPlayerA – player B now has 80 gems

2015-04-05 11:30:38.093 YonoApp[336:27031] decrementing player A gems
……..
2015-04-05 11:30:38.099 YonoApp[336:27031] decrementing player A gems
2015-04-05 11:30:38.099 YonoApp[336:27031] incrementing player B gems
……
2015-04-05 11:30:38.106 YonoApp[336:27031] incrementing player B gems
2015-04-05 11:30:38.107 YonoApp[336:27031] transferToPlayerB – player A now has 100 gems
2015-04-05 11:30:38.107 YonoApp[336:27031] transferToPlayerB – player B now has 100 gems

Using self.mutex, if thread 1 is running transferToPlayerA locking on self.mutex, thread 2 cannot run transferToPlayerB because it sees that self.mutex is locked.

Once thread 2 finishes running, it will unlock self.mutex, in which thread 2 can then lock on it and run transferToPlayerB.

This behavior allows thread 1 to modify both playerAGems and playerBGems atomically, that is, without someone else mucking around in between. When thread 1 is done, @synchronize unlocks the self.mutex, which then allows thread 2 to continue running with it holding the lock on the mutex.

Thread safety means that the data can be accessed and/or modified by multiple threads without becoming corrupt.

If you were to take away the @synchronize, you’d be getting both threads changing self.playerAGems and self.playerBGems at the same time, which is by definition, is a race condition where the output (number of gems) is dependent on the sequence or timing of other uncontrollable events such as the speed execution of our threads and how it runs.

Safe Queue

One simple and classic approach is to use Objective-C’s @synchronized capability.

In this case, @synchronized(self.data) around all of your accesses to the array will ensure that only a single thread can access the array at a time.

Even though length doesn’t modify the array, you still need to protect its access because another thread could potentially modify the array –