pthread多线程学习笔记四互斥量2使用

上篇笔记介绍了互斥量的基本定义,这篇主要介绍其使用方法。

对应其作用,关于互斥量的函数有这么几个:

1. 初始化:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);或者Pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态分配

2. 加锁:Int pthread_mutex_lock(pthread_mutex_t* mutex); Int pthread_mutex_trylock(pthread_mutex_t* mutex);

3. 解锁Int pthread_mutex_unlock(pthread_mutex_t* mutex)

4. 销毁:Int pthread_mutex_destroy(pthread_mutex_t *mutex);

具体的使用直接看个例子,从《UNIX 环境高级编程》上抄的:

/*mutex.c*/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <pthread.h>

#include <errno.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int lock_var;

time_t end_time;

void pthread1(void *arg);

void pthread2(void *arg);

int main(int argc, char *argv[])

{

pthread_t id1,id2;

pthread_t mon_th_id;

int ret;

end_time = time(NULL) + 10;

/** 互斥锁初始化*/

pthread_mutex_init(&mutex,NULL);

/** 创建两个线程*/

ret = pthread_create(&id1,NULL,(void *)pthread1,NULL);

if (ret!=0) {

perror("pthread create error.\n");

exit(-1);

}

ret = pthread_create(&id2,NULL,(void *)pthread2,NULL);

if (ret!=0) {

perror("pthread create error.\n");

}

pthread_join(id1,NULL);

pthread_join(id2,NULL);

pthread_mutex_destroy(&mutex);

exit(0);

}

void pthread1(void *arg)

{

int i;

while (time(NULL) < end_time) {

/** 互斥锁上锁*/

if (pthread_mutex_lock(&mutex)!=0) {

perror("pthread_mutex_lock");

} else {

printf("pthread1:pthread1 lock the variable %d\n",lock_var);

}

for (i=0; i<2; i++) {

sleep(1);

lock_var++;

}

/** 互斥锁解锁*/

if (pthread_mutex_unlock(&mutex)!=0) {

perror("pthread_mutex_unlock.");

} else {

printf("pthread1:pthread1 unlock the variable %d\n",lock_var);

}

sleep(1);

}

}

void pthread2(void *arg)

{

int ret;

while (time(NULL) < end_time) {

/** 测试互斥锁*/

ret = pthread_mutex_trylock(&mutex);

if (ret == EBUSY) {

printf("pthread2:the variable is locked by pthread1\n");

} else {

if (ret!=0) {

perror("pthread_mutex_trylock");

exit(1);

} else {

printf("pthread2:pthread2 got lock. The variable is %d\n",lock_var);

}

if (pthread_mutex_unlock(&mutex)!=0) {

perror("pthread_mutex_unlock");

} else {

printf("pthread2:pthread2 unlock the variable\n");

}

}

sleep(3);

}

}


需要说明的有两点:

1. lock函数会阻塞等待,直到获得锁

2. trylock函数不会阻塞等待,如果互斥量当前被锁,则返回EBUSY值。

容易出错的情形:

A

ß pthread_mutex_lock (theMutex);

ß pthread_mutex_lock (theMutex);

ß pthread_mutex_unlock (theMutex);

ß pthread_mutex_unlock (theMutex);

表面上看程序加锁两次,然后解锁两次没有错,实际上加锁第二次的时候就出错了。

B.

pthread多线程学习笔记四互斥量2使用_第1张图片pthread多线程学习笔记四互斥量2使用_第2张图片

即存在多个互斥量时的问题,两个线程都在等在另一个线程解锁才能继续往下执行。

碰到这种情况,我们一般约定一个1-2-3…的加锁顺序,所有线程都遵守这一约定才行。

但即使这样,有时候应用程序的结构使得对互斥量加锁进行排序是很困难的,如果涉及了太多的锁和数据结构,可用的函数并不能把它转换成简单的层次,那么就需要采用另外的办法。可以先释放所有的锁,然后过一段时间再试。这种情况可以使用pthread_mutex_trylock接口避免死锁。

ß 互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。设想一种简单情景:多个线程访问同一个共享资源时,并不知道何时应该使用共享资源,如果在临界区里加入判断语句,或者可以有效,但一来效率不高,二来复杂环境下就难以编写了,这是我们需要一个结构,能在条件成立时触发相应线程,进行变量修改和访问。

针对此问题,下一篇开始学习条件变量。