Results 1 to 4 of 4
Hey all,
I am wondering if pthread could make that a single thread keeps the "mutex" all the time if the time it remains unlocked is very small.
thread1
{
...
- 06-15-2010 #1Just Joined!
- Join Date
- Jun 2010
- Posts
- 2
Pthread and mutex with short unlock time.
Hey all,
I am wondering if pthread could make that a single thread keeps the "mutex" all the time if the time it remains unlocked is very small.
thread1
{
while (1)
{
lock; do_task(); unlock();
}
}
thread2
{
sleep(5seconds); lock(); print(this should appear after 5 seconds'); unlock();
}
I experiment the thread2 never getting access to the mutex and never printing the nice message. I would expect that once thread2 calls "lock", it would get the mutex as soon as thread1 calls unlock() but it does not seem to be the case.
If I add a sleep of some microseconds (100) in thread1 after unlocking the mutex, it solves the problem.
Does anyone know if this behaviour is normal?
Is there a way to configure my mutex so that thread2 receives it when unlocked?
I use
pthread_mutexattr_settype(&att, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&handle, &att);
to create my mutex.
I am running ubuntu 9.04
Thanks guys in advance !
Chuck
- 06-15-2010 #2Linux Newbie
- Join Date
- Mar 2010
- Posts
- 121
Are you using any optimisation flags? If so, turn them off and see what happens.
Otherwise, posting an example (as small as possible, but still a complete example, so people can simply cut, paste and compile) that produces the problem might help.
- 06-15-2010 #3Just Joined!
- Join Date
- Jun 2010
- Posts
- 2
Example of code.
Hey John, thanks for your answer.
Here is a sample code:
Can be compiled usingCode:#include <stdio.h> #include <stdlib.h> #include <pthread.h> int thread1(void* userdata) { __time_t t0; int delta_t,_delta_t; struct timeval tv; pthread_mutex_t* mut = (pthread_mutex_t*) userdata; gettimeofday(&tv,0); t0 = tv.tv_sec; while (1) { pthread_mutex_lock(mut); usleep(10000); gettimeofday(&tv,0); delta_t = (int) (tv.tv_sec - t0); if (delta_t != _delta_t) fprintf(stderr,"%d",delta_t); _delta_t = delta_t; pthread_mutex_unlock(mut); //usleep(1000); //uncomment to see difference. } return 0; } int thread2(void* userdata) { pthread_mutex_t* mut = (pthread_mutex_t*) userdata; sleep(5); pthread_mutex_lock(mut); fprintf(stderr,"This should appear after 5 seconds!\n"); pthread_mutex_unlock(mut); return 0; } int main() { pthread_t t1; pthread_t t2; pthread_mutex_t test_mutex; pthread_mutexattr_t mta; pthread_mutexattr_init(&mta); pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(&test_mutex,&mta); pthread_create(&t1,NULL,thread1,(void*) &test_mutex); pthread_create(&t2,NULL,thread2,(void*) &test_mutex); pthread_join(t2,NULL); //pthread_join(t1,NULL); return 0; }
gcc -o testmutex filename.c -lpthread.
I guess no optimisation flag are used.
thanks a lot,
Chuck
- 06-15-2010 #4Linux Newbie
- Join Date
- Mar 2010
- Posts
- 121
Nice example - it demonstrates the problem well. Unfortunately, the problem isn't with the mutexe itself, but with the short amount of time it's being released for.
What you've got to remember is that the scheduling of threads is absolutely unrelated to mutexes and which threads hold locks on which mutexes.
Think about the flow of execution at the end of your while-loop in thread1 - you unlock the mutex, and then immediately request it again. But thread 2 has also requested the mutex. Does it hold it? Probably not, since you've only had one or two instructions since you let it go, and that's only one or two chances for a context switch. There's no way for thread 1 to "reserve" the mutex so it can't be locked*, so thread 1 is able to grab the mutex again. At some point during thread 1's sleep(), thread 2 will come back to life, but the mutex is locked, so it can't do anything and has to wait.
To demonstrate, make the usleep(10000) (the second line in your while(1) loop) small - see what happens with values of 1, 10, 100 and 1000. I find that at around 200 it takes a couple of tries for thread 2 to see the mutex unlocked.
The remedy for this is to (1) do as little as possible inside a mutex (i.e. no sleep() calls, like you have) and, if you think you're experiencing problems with this anyway, call sched_yield() after you unlock the mutex to let the scheduler know you want to give other threads a chance.
Hope that's all clear. Sorry, I do tend to go on a bit
* That would require a mutex on the mutex...


Reply With Quote