views:

26

answers:

1

There’s an article about semaphores on OS X. The author tests the semaphore by incrementing and decrementing a static variable in two threads. With semaphore guarding the variable access, the variable ends up being zero. Without the guard the variable ends up having some bogus value. I tried the code and it works. What I don’t understand is how may the concurrent access from the two threads make a difference in the final variable value. After all it seems to me like a bunch of +1s and –1s that should be comutative, right? I feel I am missing something glaring obvious, what is it? :)

+3  A: 

The problem is that ++ / -- are not atomic. They are essentially three operations:

  1. Load
  2. Inc/dec
  3. Store

So if two threads load value simultaneously and store it also simultaneously. Difference will be 1 instead of 2.

Here is sample

Thread A Thread B
Load 5   Load 5
Inc 6    Inc 6
Store 6  Store 6
Andrey
Aha, I didn’t know about the non-atomicity. Thanks!
zoul
@zoul you should learn about it (and many other things) to be able to write multithreaded programs :)
Andrey
I admit that I don’t know much about multithreading. But the modern threading tools (like `@synchronized`, Grand Central Dispatch or various locking classes in my case) make many things easy so people can get surprisingly far without knowing about atomic increments :)
zoul
@zoul that is critical illusion. they let people *code* easily, but the safeness, quality and robustness of code still depends on developer's knowledge and understanding of fundamental concepts. they are *instruments*, but not devices that think for you.
Andrey
The point is that they are usually easier to think about and therefore easier to get right. For example the `@synchronized` directive will simply guard a critical section against a concurrent access. I would venture to say that I can use such a tool effectively and correctly without knowing anything about atomicity.
zoul
@zoul again, from my rich experience in multithreading, i can say that you are partially correct. with `@synchronized` you can write: unsafe code (for example lock against public pointers), unoptimal (you want to just increment variable and you use @synchronized instead of atomic operations (http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-124887)) or cause deadlock
Andrey
You’re right. Thank you once again for the answer and спасибо for the discussion.
zoul