views:

169

answers:

7

If I understand correctly, then foo1() fails to unlock &private_value_. As a result, foo2()'s thread_mutex_lock does not work since foo1() never released it.

What are the other consequences?

int main ( ... )

foo1();
foo2();

return 0;
}

foo1()
{
 pthread_mutex_lock(&private_value_);
 do something 
 // no unlock!
}

foo2()
{
 pthread_mutex_lock(&private_value_)
 do something
 pthread_mutex_unlock(&private_value_);
}
+3  A: 

The mutex works fine. It's doing what it is meant to do. The thread will block after foo1() exits until the mutex is obtained by foo2.

San Jacinto
But isn't foo1() supposed to unlock the mutex it acquired?How can foo2() ever obtain the mutex if foo1() never releases it?
Kevin
foo2 will NEVER obtain it until foo1 releases it. Foo1 itself does not own the mutex. I assume the mutex is part of a class and the mutex lock/unlock statements are indeed operating on the same common mutex. In your code, if you do not explicitly unlock the mutex, it is considered locked and nothing else can obtain the lock --not even the same thread.
San Jacinto
Are you perchance coming from a C# or java background where monitors offer scoped locks that are managed automatically? This is not the case when using the prthread library calls.
San Jacinto
Though there about a zillion C++ libraries that do exactly this.
anon
A: 

If only foo2 gets called everything will run normal. If foo1 gets called then, if foo2 gets called or any other function that requires the mutex it will lock up forever.

crazyx
+1  A: 

This is why people migrate to languages that offer scope-based solutions, like C++ and RAII. The mutex is working as intended, but the writer of the first function forgot a small call, and now the application halts.

DeadMG
+1  A: 

It's a bug if a lock is taken on a mutex and nothing ever releases the lock.

However, that doesn't necessarily mean that foo1() has to release the lock, but something must.

There are patterns where one function will acquire a lock, and another will release it. But you need to take special care that these more complex mutex handling patterns are coded correctly. You might be looking at an example of this (and the boiled-down snippet in the question doesn't include that additional complexity).

And as Neil Butterworth mentioned in a comment, there are many situations in C++ where a mutex will be managed by an RAII class, so the lock will be released automatically when the 'lock manager' object gets destroyed (often by going out of scope). In this case, it may not be obvious that the lock is being released, since that is done as a side effect of the variable merely going out of scope.

Michael Burr
+3  A: 

There seems to be some confusion here between how the program should have been written and how the program, as currently written, will behave.

This code will cause deadlock, and this does not indicate that there is something wrong with how the mutexes are working. They're working exactly how they are supposed to: If you try to re-acquire a non-recursive mutex that is already locked, your code will block until the mutex is unlocked. That's how it's supposed to work.

Since this code is single-threaded, the blocking in foo2 will never end, and so your program will deadlock and not progress. That is most likely not how the program should work (because it's not a very useful program that way). The error is not in how the mutexes are functioning, but in how the programmer chose to employ them. The programmer should have put an unlock call at the end of foo1.

Tyler McHenry
No you are wrong this will not necessarily block. `If the mutex type is PTHREAD_MUTEX_RECURSIVE, then the mutex maintains the concept of a lock count. When a thread successfully acquires a mutex for the first time, the lock count is set to one. Every time a thread relocks this mutex, the lock count is incremented by one.`So if it is initialized with an attibute that sets `PTHREAD_MUTEX_RECURSIVE` the bug of this program will be hidden and the behavior will seem "normal".
Jens Gustedt
I'm aware of that. Did you read the part where I wrote "non-recursive mutex"? Additionally, the OP's description of the behavior that he observed indicates that the mutex is in this case not recursive.
Tyler McHenry
@Tyler: Didn't mean to offend you, but you put the "will" in emphs, and I wanted to make this point clear.
Jens Gustedt
If the mutex is an error-checking type, it won't deadlock either - the second attempt to lock will return `EDEADLK` (which would fit the OP's characterisation of the second `pthread_mutex_lock` "not working").
caf
There is no deadlock in the posted code.
anon
+1  A: 

No, it does not necessarily block. All depends on your private_value_ variable. pthread_mutex_t can show different behavior according to the properties that were set when the variable was initialized. See http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html

Jens Gustedt
+1  A: 

To answer the question:

There are no other consequences other than a deadlock (since your example is single threaded and makes the calls synchronously)..

carribus