#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int g_num = 0;
void work1(void *arg)
{
while(1)
{
puts("work thread 1");
pthread_mutex_lock(&lock))
g_num++;
sleep(1);
pthread_mutex_unlock(&lock);
}
}
void work2(void *arg)
{
while(1)
{
puts("work thread 2");
pthread_mutex_lock(&lock))
g_num++;
sleep(1);
pthread_mutex_unlock(&lock);
}
}
int main()
{
pthread_t thread_id1, thread_id2;
pthread_create(&thread_id1, NULL, (void *)work1, NULL);
pthread_create(&thread_id2, NULL, (void *)work2, NULL);
pthread_join(thread_id1, NULL);
pthread_join(thread_id2, NULL);
printf("%ld %ld", thread_id1, thread_id2);
return 0;
}
看看上面这段程序:程序在运行一段时间后,线程1和线程2就不会切换了。猜测是原因是因为pthread_mutex_lock是一个阻塞操作,线程1在拥有锁的时候也陷入休眠,此时线程2请求锁失败也让自己休眠,而线程1释放锁之后,线程2依然处于休眠中,此次线程1再次获取锁,过了一会儿,线程2再次请求锁,于是再次休眠,如此循环。然后它再也获取不到锁了。
在把代码中的sleep调用放在加锁区域外的时候,这个问题得到了解决。因为当线程1解锁之后,他让自己休眠了,从而使线程2有足够的时间等到这把锁。
在使用pthread_mutex_trylock的时候,即使将sleep调用放在加锁区,线程2请求锁失败,它会立即返回,然后再次请求锁。所以线程2总有机会能获取到锁。
所以这是否意味着pthread_mutex_trylock优于pthread_mutex_lock?
PS:很多书籍都提到过,在线程中调用sleep不是一个好习惯。在确实需要使用的时候,使用select或者pthread_cond_timedwait来模拟是一个常用的做法。
因我对pthread的了解十分有限,故本文可能有错误,请看到的朋友不吝赐教。