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:
- Load
- Inc/dec
- 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
2010-10-09 16:52:46
Aha, I didn’t know about the non-atomicity. Thanks!
zoul
2010-10-09 16:54:18
@zoul you should learn about it (and many other things) to be able to write multithreaded programs :)
Andrey
2010-10-09 16:55:09
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
2010-10-09 16:59:46
@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
2010-10-09 17:06:50
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
2010-10-09 17:18:50
@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
2010-10-09 17:46:05
You’re right. Thank you once again for the answer and спасибо for the discussion.
zoul
2010-10-09 19:43:55