目录
- 互斥量
- 死锁
- 未解锁
- 重复加锁
- 多个锁
- 读写锁
- 案例
互斥量
接上一章,卖票存在线程安全问题。
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){//卖票while(1){//加锁pthread_mutex_lock(&mutex);if(tickets>0){usleep(3000);printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);tickets--;}else{//解锁pthread_mutex_unlock(&mutex);break;}//解锁pthread_mutex_unlock(&mutex);}return NULL;
}
int main(){//初始化互斥量pthread_mutex_init(&mutex,NULL);//创建3个子线程pthread_t tid1,tid2,tid3;pthread_create(&tid1,NULL,sellticket,NULL);pthread_create(&tid2,NULL,sellticket,NULL);pthread_create(&tid3,NULL,sellticket,NULL);//回收子线程的资源,阻塞pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_exit(NULL);//退出主线程//释放互斥量资源pthread_mutex_destroy(&mutex);return 0;
}
不同的线程卖出几十张之后,切换到另一个线程来卖
虽然解决了数据安全的问题,但效率降低了,变成串行
死锁
未解锁
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){//卖票while(1){//加锁pthread_mutex_lock(&mutex);if(tickets>0){usleep(3000);printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);tickets--;}else{//解锁pthread_mutex_unlock(&mutex);break;}//解锁//pthread_mutex_unlock(&mutex);}return NULL;
}
int main(){//初始化互斥量pthread_mutex_init(&mutex,NULL);//创建3个子线程pthread_t tid1,tid2,tid3;pthread_create(&tid1,NULL,sellticket,NULL);pthread_create(&tid2,NULL,sellticket,NULL);pthread_create(&tid3,NULL,sellticket,NULL);//回收子线程的资源,阻塞pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_exit(NULL);//退出主线程//释放互斥量资源pthread_mutex_destroy(&mutex);return 0;
}
未解锁会无法切换线程
重复加锁
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int tickets=1000;//局部变量就是每个人卖100张,全局变量就是一起卖100张,所有线程共享一份资源
//创建一个互斥量
pthread_mutex_t mutex;
void * sellticket(void * arg){//卖票while(1){//加锁pthread_mutex_lock(&mutex);pthread_mutex_lock(&mutex);if(tickets>0){usleep(3000);printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets);tickets--;}else{//解锁pthread_mutex_unlock(&mutex);break;}//解锁pthread_mutex_unlock(&mutex);}return NULL;
}
int main(){//初始化互斥量pthread_mutex_init(&mutex,NULL);//创建3个子线程pthread_t tid1,tid2,tid3;pthread_create(&tid1,NULL,sellticket,NULL);pthread_create(&tid2,NULL,sellticket,NULL);pthread_create(&tid3,NULL,sellticket,NULL);//回收子线程的资源,阻塞pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_exit(NULL);//退出主线程//释放互斥量资源pthread_mutex_destroy(&mutex);return 0;
}
也会无法执行
多个锁
多线程对多个锁进行操作时
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>//创建两个互斥量
pthread_mutex_t mutex1,mutex2;void * workA(void * arg){pthread_mutex_lock(&mutex1);sleep(1);pthread_mutex_lock(&mutex2);printf("workA...\n");pthread_mutex_unlock(&mutex2);pthread_mutex_unlock(&mutex1);return NULL;
}void * workB(void * arg){pthread_mutex_lock(&mutex2);sleep(1);pthread_mutex_lock(&mutex1);printf("workB...\n");pthread_mutex_unlock(&mutex1);pthread_mutex_unlock(&mutex2);return NULL;
}int main(){//初始化互斥量pthread_mutex_init(&mutex1,NULL);pthread_mutex_init(&mutex2,NULL);//创建2个子线程pthread_t tid1,tid2;pthread_create(&tid1,NULL,workA,NULL);pthread_create(&tid2,NULL,workB,NULL);//回收子线程资源pthread_join(tid1,NULL);pthread_join(tid2,NULL);//释放互斥量资源pthread_mutex_destroy(&mutex1);pthread_mutex_destroy(&mutex2);return 0;
}
读写锁
同时去读共享资源没有问题,但是互斥锁的排他性太强了,读没有影响,互斥锁读都不行
案例
8个线程操作同一个全局变量
3个线程不定时写一个全局变量,其余5个线程不定时的读一个全局变量
#define _XOPEN_SOURCE 500
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>//创建一个共享数据
int num=1;
pthread_rwlock_t rwlock;void * writeNum(void * arg){while(1){pthread_rwlock_wrlock(&rwlock);num++;printf("++write,tid:%ld,num:%d\n",pthread_self(),num);pthread_rwlock_unlock(&rwlock);usleep(100);}return NULL;
}void * readNum(void * arg){while(1){pthread_rwlock_rdlock(&rwlock);printf("==read,tid:%ld,num:%d\n",pthread_self(),num);pthread_rwlock_unlock(&rwlock);usleep(100);}return NULL;
}int main(){pthread_rwlock_init(&rwlock,NULL);//创建3个写线程,5个读线程pthread_t wtids[3],rtids[5];for(int i=0;i<3;i++){pthread_create(&wtids[i],NULL,writeNum,NULL);}for(int i=0;i<5;i++){pthread_create(&rtids[i],NULL,readNum,NULL);}//设置线程分离for(int i=0;i<3;i++){pthread_detach(wtids[i]);}for(int i=0;i<5;i++){pthread_detach(rtids[i]);}//主线程退出pthread_exit(NULL);pthread_rwlock_destroy(&rwlock);return 0;
}