线程同步--互斥量
线程的最大特点是资源的共享性,但资源共享中带来了对共享资源的竞争问题;解决竞争问题的途径是保证对共享资源的互斥访问,所谓互斥访问是指一个执行单元在访问共享资源的时候,他她的指向单元被禁止访问,以保证线程之间同步进行;同步是了保证在同一个时刻只有一个线程对资源进行操作,linux下提供了多种方式来处理线程同步,最常用的是互斥锁,条件变量和信号。
互斥量:
互斥量用pthread_mutex_t 数据类型来表示;操作函数集如下所示:
//该函数初始化一个互斥体变量,如果参数attr 为NULL,则互斥体变量mutex 使用默认的属性。
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t* attr ); // 该函数用来锁住互斥体变量。如果参数mutex 所指的互斥体已经被锁住了,那么发出调用的线程将被阻塞直到其他线程对mutex 解锁。 int pthread_mutex_lock(pthread_mutex_t *mutex );
//该函数用来锁住mutex 所指定的互斥体,但不阻塞。如果该互斥体已经被上锁,该调用不会阻塞等待,而会返回一个错误代码。 int pthread_mutex_trylock( pthread_t *mutex);
//该函数用来对一个互斥体解锁。如果当前线程拥有参数mutex 所指定的互斥体,该调用将该互斥体解锁。 int pthread_mutex_unlock( pthread_mutex_t *mutex ); //该函数用来释放分配给参数mutex 的资源。调用成功时返回值为0, 否则返回一个非0 的错误代码。 int pthread_mutex_destroy (pthread_mutex_t *mutex );
下面是没有用互斥的实例:
#include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #define FOR_COUNT 20 int myglobal;/*全局变量,主线程和子线程共享*/ void * thread_function(void *arg)/*线程函数*/ { int i,j; for(i = 0; i<FOR_COUNT; i++) { j = myglobal; j = j+1; fflush(stdout); sleep(1); myglobal = j; printf("."); printf("thrad global = %d\n",myglobal); } return NULL; } int main() { pthread_t mythread; int i; if(pthread_create(&mythread, NULL, thread_function, NULL)) { printf("error creating thead."); abort(); } /*主线程中对变量进行操作*/ for(i=0; i < FOR_COUNT; i++) { myglobal = myglobal + 1; printf("o"); printf("main global = %d\n",myglobal); fflush(stdout); sleep(1); } if(pthread_join(mythread,NULL)) { printf("error joining thread"); abort(); } printf("\n mygloabl equals %d\n", myglobal); exit(0); }
结果如下所示:可以看出 两次程序运行的结果不一样,因为线程是并行的,不能假设调度策略;
omain global = 19 omain global = 27 .thrad global = 19 .thrad global = 27 omain global = 20 omain global = 28 .thrad global = 20 .thrad global = 29 omain global = 21 omain global = 30 .thrad global = 21 .thrad global = 31 omain global = 22o main global = 32 .thrad global = 22 .thrad global = 33 mygloabl equals 22 mygloabl equals 33
使用互斥量(例子1):静态分配互斥量
#include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #define FOR_COUNT 20 int myglobal; /* PTHREAD_MUTEX_INITIALIZER用于初始化静态分配的互斥量*/ pthread_mutex_t mutext = PTHREAD_MUTEX_INITIALIZER; void * thread_function(void *arg) { int i,j; for(i = 0; i<FOR_COUNT; i++) { pthread_mutex_lock(&mutext); j = myglobal; j = j+1; fflush(stdout); myglobal = j; printf("."); printf("thrad global = %d\n",myglobal); pthread_mutex_unlock(&mutext); sleep(1);//等待让另外一个线程运行 } return NULL; } int main() { pthread_t mythread; int i; if(pthread_create(&mythread, NULL, thread_function, NULL)) { printf("error creating thead."); abort(); } for(i=0; i < FOR_COUNT; i++) { pthread_mutex_lock(&mutext); myglobal = myglobal + 1; printf("o"); printf("main global = %d\n",myglobal); pthread_mutex_unlock(&mutext); fflush(stdout); sleep(1);//等待让另外一个线程运行 } if(pthread_join(mythread,NULL)) { printf("error joining thread"); abort(); } pthread_mutex_destroy(&mutext); printf("\n mygloabl equals %d\n", myglobal); exit(0); }
使用互斥量(例子2):动态分配互斥量
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> struct foo { int f_count; pthread_mutex_t f_lock; }; struct foo * foo_alloc() { struct foo * fp; if((fp = (struct foo *)malloc(sizeof(struct foo))) != NULL) { if(pthread_mutex_init(&fp->f_lock, NULL) != 0) { free(fp); return NULL; } fp->f_count = 1; } return fp; } void foo_hold(struct foo * fp) { pthread_mutex_lock(&fp->f_lock); fp->f_count++; printf("thread %u,count is %d\n",(unsigned int)pthread_self(), fp->f_count); pthread_mutex_unlock(&fp->f_lock); } void foo_rele(struct foo *fp) { pthread_t tid = pthread_self(); pthread_mutex_lock(&fp->f_lock); if(--fp->f_count == 0) { pthread_mutex_unlock(&fp->f_lock); pthread_mutex_destroy(&fp->f_lock); free(fp); printf("finally destory the global\n"); } else { pthread_mutex_unlock(&fp->f_lock); printf("the thread %u doesn`t need the source\n", (unsigned int )tid); } } void * pthread_fun1(void * fp) { struct foo * pfoo = (struct foo *)fp; foo_hold(pfoo); sleep(2); foo_rele(pfoo); pthread_exit(NULL); printf("pthread1 exit\n"); } void * pthread_fun2(void *fp ) { struct foo * pfoo = (struct foo *)fp; foo_hold(pfoo); sleep(1); foo_rele(pfoo); pthread_exit(NULL); printf("pthread2 exit\n"); } int main() { int err; pthread_t thread1, thread2; /*分配全局变量*/ struct foo * fp; fp = foo_alloc(); err = pthread_create(&thread1, NULL,pthread_fun1, (void *)fp); if( err != 0 ) { printf("cant not create thread1:%s\n", strerror(err)); exit(1); } err = pthread_create(&thread2, NULL,pthread_fun2, (void *)fp); if( err != 0 ) { printf("cant not create thread1:%s\n", strerror(err)); exit(1); } sleep(1); foo_rele(fp); /*主线程等待子线程退出*/ if(pthread_join(thread1,NULL) == 0) printf("pthrad1 exit\n"); if(pthread_join(thread2,NULL) == 0 ) printf("pthrad2 exit\n"); exit(0); }
程序运行结果:
thread 3079039856,count is 2 thread 3070647152,count is 3 the thread 3079042752 doesn`t need the source the thread 3070647152 doesn`t need the source finally destory the global pthrad1 exit pthrad2 exit
欢迎评论交流