线程同步与互斥
线程共享进程的资源和地址空间,对这些资源进行操作时,必须考虑线程间同步与互斥问题
三种线程同步机制
•互斥锁
•信号量
•条件变量
互斥锁更适合同时可用的资源是惟一的情况
信号量更适合同时可用的资源为多个的情况
互斥锁
用简单的加锁方法控制对共享资源的原子操作
只有两种状态: 上锁、解锁
可把互斥锁看作某种意义上的全局变量
在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作
若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止
互斥锁保证让每个线程对共享资源按顺序进行原子操作
互斥锁分类
区别在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要阻塞等待
快速互斥锁
•调用线程会阻塞直至拥有互斥锁的线程解锁为止
•默认为快速互斥锁
检错互斥锁
•为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息
互斥锁主要包括下面的基本函数:
互斥锁初始化:pthread_mutex_init()
互斥锁上锁:pthread_mutex_lock()
互斥锁判断上锁:pthread_mutex_trylock()
互斥锁解锁:pthread_mutex_unlock()
消除互斥锁:pthread_mutex_destroy()
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 5 #define THREAD_NUM 3 6 #define REPEAT_TIMES 5 7 #define DELAY 4 8 9 pthread_mutex_t mutex; 10 11 void *thrd_func(void *arg); 12 13 int main(){ 14 pthread_t thread[THREAD_NUM]; 15 int no; 16 void *tret; 17 18 srand((int)time(0)); 19 // 创建快速互斥锁(默认),锁的编号返回给mutex 20 pthread_mutex_init(&mutex,NULL); 21 22 // 创建THREAD_NUM个线程,每个线程号返回给&thread[no],每个线程的入口函数均为thrd_func,参数为 23 for(no=0;no<THREAD_NUM;no++){ 24 if (pthread_create(&thread[no],NULL,thrd_func,(void*)no)!=0) { 25 printf("Create thread %d error!\n",no); 26 exit(1); 27 } else 28 printf("Create thread %d success!\n",no); 29 } 30 31 // 对每个线程进行join,返回值给tret 32 for(no=0;no<THREAD_NUM;no++){ 33 if (pthread_join(thread[no],&tret)!=0){ 34 printf("Join thread %d error!\n",no); 35 exit(1); 36 }else 37 printf("Join thread %d success!\n",no); 38 } 39 // 消除互斥锁 40 pthread_mutex_destroy(&mutex); 41 return 0; 42 } 43 44 void *thrd_func(void *arg){ 45 int thrd_num=(void*)arg; // 传入的参数,互斥锁的编号 46 int delay_time,count; 47 48 // 对互斥锁上锁 49 if(pthread_mutex_lock(&mutex)!=0) { 50 printf("Thread %d lock failed!\n",thrd_num); 51 pthread_exit(NULL); 52 } 53 54 printf("Thread %d is starting.\n",thrd_num); 55 for(count=0;count<REPEAT_TIMES;count++) { 56 delay_time=(int)(DELAY*(rand()/(double)RAND_MAX))+1; 57 sleep(delay_time); 58 printf("\tThread %d:job %d delay =%d.\n",thrd_num,count,delay_time); 59 } 60 61 printf("Thread %d is exiting.\n",thrd_num); 62 // 解锁 63 pthread_mutex_unlock(&mutex); 64 65 pthread_exit(NULL); 66 }
和上一版本的程序差异在于有没有锁,有锁的情况下,必须等"thread x is exiting."之后其他线程才能继续。