There are probably many reasons why pthread_mutex objects and APIs that manipulate those objects are used instead of everyone coding up their own synchronization primitives. A coupl eof the more important ones.
There are probably many reasons why pthread_mutex objects and APIs that manipulate those objects are used instead of everyone coding up their own synchronization primitives. A coupl eof the more important ones: much like many other objects and functionality that are useful to a wide audience, it makes sense to standardize that functionality so that people don't have to reinvent the wheel and so they can use and recognize standard patterns and idioms. In other words, there are pthread mutex APIs for the same reason there are standard string manipulation functions.
Synchronization techniques are notoriously complicated and difficult to get right. So it's best to have a vetted library of code that performs this functionality. Even if it were OK to reinvent the wheel umpteen million times, having 99% of those implementations with serious flaws isn't a great situation.
For example, pthreads handles issues like memory barriers and atomicity which are not addressed properly in the example you have in your question. Considering the example in the question: there's at least one serious problem; it has a race condition where two threads could enter the critical section concurrently since the test of the flag and setting it to 0 aren't performed atomically.
First, if your code would work, the second thread will skip entirely the critical section. You'd have to place a loop or something there. Also, take into account the fact that the scheduler may preempt your thread anywhere.
What happens if thread A does the test and is preempted before changing flag and thread B is allowed to make the test and enter the critical section being preempted soon afterwards. You'll have two threads there.
So when threadA returns, it sees the flag is to wait, as threadB is there, so it waits. So what's the problem? – kingsmasher1 Aug 17 at 7:24 A thread can be put on hold at almost any time by the scheduler.
In the scenario that Mihai describes, thread A is put on hold right after the check of flag. So it's already "inside the critical section" (the instruction pointer register points to the first instruction inside the if block) but hasn't set flag to 1 yet. Now Thread B can enter the critical section because flag is still 0 and be put on hold somewhere in there.
Now, when thread A is then resumed, it can run in parallel to B inside the critical section. – dosendoc Aug 17 at 7:33 Ahhh..I got it. – kingsmasher1 Aug 17 at 7:34 Also, that's not the only problem with your solution.
There are two more important ones: As long as flag is not declared volatile, the compiler is allowed to cache the value of flag in a register for optimization, which means that thread B would never see the newly assigned value 1 even after thread A is well within the critical section. Also, even if the variable were declared volatile, there would still be the problem that B cannot see the changes made by A if they're running on different cores and the caches haven't been synchronized yet, which causes even more timing issues. – dosendoc Aug 17 at 7:41 1 Note that with gcc volatile is neither necessary nor sufficient for atomic semantics.
You need to use the GCC atomics builtins, or then the C++0x or C1X atomic. – janneb Aug 17 at 8:32.
Firstly, you should use atomic memory operations (see InterlockedCompareExchange() in MSVC and __sync_val_compare_and_swap() in GCC). Secondly, this code will work, but only if second thread shouldn't wait when first sets flag back to 1. If it should, you wil end with loop, which would consume all your CPU.In that case you should use something, that will cause waiting thread to sleep (for example pthread_mutex_lock()).
Since you have tagged you question with "linux", one might add that pthreads are built on top of something called "futexes", or "fast userspace mutexes". As the name might imply, the fast path, namely locking and unlocking an uncontended mutex, does NOT require a syscall, it's all done in userspace. FWIW, AFAIK Windows does something similar as well.
– kingsmasher1 Aug 17 at 8:46 2 No, I mean to say that the concurrency primitives provided by the OS are highly optimized, well documented, implemented by experts who know what they're doing, and as opposed to the code snippet in the OP, they actually work. – janneb Aug 17 at 8:50 Did you try google "gcc atomic builtins"? For me one of the first hits is gcc.gnu.
Org/onlinedocs/gcc/Atomic-Builtins. Html , which I suspect is what you're looking for... – janneb Aug 17 at 8:51.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.