互斥量,运行程序元锁住某个对象,使得每次只能有一个线程访问它;为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁它 ;
基本函数与用于信号量的函数非常相似
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutext, const pthread_mutexattr_t *mutexattr);
int pthread_mutext_lock(pthread_mutex_t *mutex);
int pthread_mutext_unlock(pthread_mutex_t *mutex);
int pthread_mutext_destory(pthread_mutex_t *mutex);
这些函数成功,返回0,失败返回错误代码,不会设置errno,所以必须对返回代码进行检查
与信号量类似,这些参数都是一个先前声明过的对象的指针,对互斥量来说,这个对象类型为pthread_mutext_t。
pthread_mutext_init函数中的属性参数与性能我们设置互斥量的属性,而属性控制着互斥量的行为;
熟悉类型默认是fast,但他有一个缺点:如果程序试图对一个已经家了锁的互斥量调用pthread_mutex_lock,程序就会阻塞;
但是拥有信号量的线程正是被阻塞的线程,所以互斥量就永远不会被解锁了,程序也就进入“死锁”状态;
解决方法:就是改变互斥量的属性,让属性来检查这种情况并返回一个错误,或者让它递归操作,给同一个线程加上多个锁,但是“lock”操作和“unlock”操作必须相对应;
==============
互斥量
/************************************************************************* > File Name: thread4.c > Author: > Mail: > Created Time: 2016年03月27日 星期日 16时37分11秒 ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<pthread.h> #include<semaphore.h> void *thread_function(void *arg); //声明了互斥量,工作区,控制结束的变量 pthread_mutex_t work_mutex; //protect both work_area and time_to_exit #define WORK_SIZE 1024 char work_area[WORK_SIZE]; int time_to_exit = 0; int main(){ int res; pthread_t a_thread; void *thread_result; res = pthread_mutex_init(&work_mutex,NULL);//初始化mutex if(res!=0){ perror("mutex initialization failed"); exit(EXIT_FAILURE); } res = pthread_create(&a_thread,NULL,thread_function,NULL); //启动新的thread if(res != 0){ perror("Thread creation failed"); exit(EXIT_FAILURE); } pthread_mutex_lock(&work_mutex);//首先给工作区work_area加锁 printf("input some text. Enter 'end' to finish\n"); while(!time_to_exit){ fgets(work_area,WORK_SIZE,stdin);//读入文本 pthread_mutex_unlock(&work_mutex);//解锁允许其他进程访问它,来统计 while(1){ pthread_mutex_lock(&work_mutex);//周期性加锁, if(work_area[0] != '\0'){//检查其他线程是否统计完毕 //work_area[0] = '\0'表示统计完毕,break出while(1) //否则,解锁,等待 pthread_mutex_unlock(&work_mutex); sleep(1); }else{ break; } } } pthread_mutex_unlock(&work_mutex); printf("\nWaiting for thread to finish...\n"); res = pthread_join(a_thread,&thread_result); if(res!=0){ perror("Thread join failed"); exit(EXIT_FAILURE); } printf("Thread join\n"); pthread_mutex_destroy(&work_mutex); exit(EXIT_FAILURE); } void *thread_function(void *arg){ sleep(1); pthread_mutex_lock(&work_mutex);//新的thread启动对mutex进行加锁 //如果mutex已经加锁,这个调用将阻塞直到他被释放为止 //一旦获得访问权,就检查是否申请退出程序,end<>work_area[]比较 //如果work_area[]==end那么,设置time_to_exit,work_area[0] = '\0',exit //如果没有申请退出程序,那么统计字符个数,work_area[0] = '\0' while(strncmp("end",work_area,3) != 0){ printf("you input %d characters\n",strlen(work_area)-1); work_area[0] = '\0';//我们利用work_area[0]=='\0'的方式,通知输入 //线程,本线程已经完成统计字符工作; pthread_mutex_unlock(&work_mutex);//解锁 sleep(1);//等待main线程继续运行 pthread_mutex_lock(&work_mutex); //尝试加锁,如果成功,就检查是否main线程又有新的字符要处理 while(work_area[0] == '\0'){ pthread_mutex_unlock(&work_mutex);//如果没有字符要处理,解锁 sleep(1);//等待 pthread_mutex_lock(&work_mutex);//尝试加锁 } } time_to_exit = 1; work_area[0] = '\0'; pthread_mutex_unlock(&work_mutex); pthread_exit(0); }
编译方式
lizhen@lizhen:~/basic$ cc -D_REENTRANT thread4.c -o thread4 -lpthread
运行方式
lizhen@lizhen:~/basic$ ./thread4 input some text. Enter 'end' to finish hello you input 5 characters end Waiting for thread to finish... Thread join lizhen@lizhen:~/basic$