赞
踩
pthread_mutex_t mutex;
pthread_mutex_init(&mutex);---相当于mutex=1
pthread_mutex_lock(&mutex); -- mutex = 0
pthread_mutex_unlock(&mutex); -- mutex = 1
pthread_mutex_destroy(&mutex);
注意:必须在所有操作共享资源的线程上都加上锁否则不能起到同步的效果。
死锁并不是linux提供给用户的一种使用方法,而是由于用户使用互斥锁不当引起的一种现象。
常见的死锁有两种:
第一种:自己锁自己,如下图代码片段
第二种 线程A拥有A锁,请求获得B锁;线程B拥有B锁,请求获得A锁,这样造成线程A和线程B都不释放自己的锁,而且还想得到对方的锁,从而产生死锁,如下图所示:
如何解决死锁:
让线程按照一定的顺序去访问共享资源
在访问其他锁的时候,需要先将自己的锁解开
调用pthread_mutex_trylock,如果加锁不成功会立刻返回
读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。写独占、读共享。
读写锁使用场合:读写锁非常适合于对数据结构读的次数远大于写的情况。
读写锁特性
读并行,写独占,当读写同时等待锁的时候写的优先级高。
定义一把读写锁 pthread_rwlock_t rwlock;
初始化 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
函数参数
销毁读写锁 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
加读锁 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
尝试加读锁 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
加写锁 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
尝试加写锁 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
解锁 int pthread_rwlock_unlock(&pthread_rwlock_t *rwlock);
/************************************************************************************* * @Descripttion : 读写锁测试例程:5个读线程、3个写线程不定时操作同一全局资源 * @version : 1.0 * @Author : liuziyan * @Date : 2021-07-24 21:02:57 * @LastEditors : Lzy * @LastEditTime : 2021-07-24 22:06:06 * @FilePath : /day9/pthread_rwlock.c * @Copyright 2021 liuziyan, All Rights Reserved. *************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <stddef.h> int number = 0; //定义一把读写锁 pthread_rwlock_t rwlock; //写线程回调函数 void *thread_write(void *arg) { int i = *(int *)arg; int cur=0; while (1) { //加写锁 pthread_rwlock_wrlock(&rwlock); cur = number; cur++; number = cur; printf("[%d]-W:[%d]\n",i,cur); //解锁 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } //读线程回调函数 void *thread_read(void *arg) { int i = *(int *)arg; int cur = 0; while(1) { //加读锁 pthread_rwlock_rdlock(&rwlock); cur = number; printf("[%d]-R:[%d]\n",i,cur); //解锁 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } int main() { int arr[8]; pthread_t thread[8]; //读写锁初始化 pthread_rwlock_init(&rwlock,NULL); //创建3个写线程 for (size_t i = 0; i < 3; i++) { arr[i] = i; pthread_create(&thread[i], NULL, thread_write, &arr[i]); } //创建5个写线程 for (size_t i = 3; i < 8; i++) { arr[i] = i; pthread_create(&thread[i], NULL, thread_read, &arr[i]); } for (size_t j = 0; j < 8; j++) { pthread_join(thread[j], NULL); } //销毁读写锁 pthread_rwlock_destroy(&rwlock); return 0; }
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
int pthread_cond_signal(pthread_cond_t *cond);
上述代码中,生产者线程调用pthread_cond_signal函数会使消费者线程在pthread_cond_wait处解除阻塞。
/************************************************************************************* * @Descripttion : 条件变量pthread_cond_t进行生产者消费者模型。 * @version : 1.0 * @Author : liuziyan * @Date : 2021-07-26 10:31:18 * @LastEditors : Lzy * @LastEditTime : 2021-07-26 11:27:46 * @FilePath : /day9/pthread_cond.c * @Copyright 2021 liuziyan, All Rights Reserved. *************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> typedef struct node { int data; struct node *next; } NODE; NODE *head = NULL; //链表长度 int len = 0; //定义一把锁 pthread_mutex_t mutex; //定义条件变量 pthread_cond_t cond; //生产者模型(头插法生成链表) void *producer(void *args) { NODE *pNode = NULL; while (1) { //生产一个节点 pNode = (NODE *)malloc(sizeof(NODE)); if (pNode == NULL) { perror("malloc error:"); exit(-1); } //加锁 pthread_mutex_lock(&mutex); len++; pNode->data = len; printf("P:[%d]\n", pNode->data); pNode->next = head; head = pNode; //解锁 pthread_mutex_unlock(&mutex); //通知消费者线程解除阻塞 pthread_cond_signal(&cond); //防止生产过快而死 sleep(rand() % 3); } pthread_exit(NULL); } void *consumer(void *args) { NODE *pNode = NULL; while (1) { //加锁 pthread_mutex_lock(&mutex); if(head == NULL) { //若条件不满足,则阻塞等待并解锁 //若条件满足(被生产者线程调用pthread_cond_signal函数通知),则加锁该线程解除阻塞。 pthread_cond_wait(&cond,&mutex); } printf("C:[%d]\n", head->data); pNode = head; head = head->next; len--; //解锁 pthread_mutex_unlock(&mutex); //释放该节点内存 free(pNode); pNode = NULL; sleep(rand() % 3); } pthread_exit(NULL); } int main() { int ret; pthread_t thread1; pthread_t thread2; //随机数种子 srand(time(NULL)); //互斥锁初始化 pthread_mutex_init(&mutex, NULL); //条件变量初始化 pthread_cond_init(&cond, NULL); ret = pthread_create(&thread1, NULL, producer, NULL); if (ret != 0) { printf("pthread_create error, [%s]\n", strerror(ret)); return -1; } ret = pthread_create(&thread2, NULL, consumer, NULL); if (ret != 0) { printf("pthread_create error, [%s]\n", strerror(ret)); return -1; } //等待线程结束 pthread_join(thread1, NULL); pthread_join(thread2, NULL); //释放互斥锁 pthread_mutex_destroy(&mutex); //释放条件变量 pthread_cond_destroy(&cond); return 0; }
/************************************************************************************* * @Descripttion : 条件变量pthread_cond_signal激活多个线程同时激活。 * 注意访问地址错误问题! * @version : 1.0 * @Author : liuziyan * @Date : 2021-07-26 14:15:34 * @LastEditors : Lzy * @LastEditTime : 2021-07-26 14:34:48 * @FilePath : /day9/pthread_cond2.c * @Copyright 2021 liuziyan, All Rights Reserved. *************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> typedef struct node { int data; struct node *next; } NODE; NODE *head = NULL; //链表长度 int len = 0; //定义一把锁 pthread_mutex_t mutex; //定义条件变量 pthread_cond_t cond; //生产者模型(头插法生成链表) void *producer(void *args) { NODE *pNode = NULL; int n = *(int *)args; while (1) { //生产一个节点 pNode = (NODE *)malloc(sizeof(NODE)); if (pNode == NULL) { perror("malloc error:"); exit(-1); } //加锁 pthread_mutex_lock(&mutex); len++; pNode->data = len; printf("P[%d]:[%d]\n", n, pNode->data); pNode->next = head; head = pNode; //解锁 pthread_mutex_unlock(&mutex); //通知至少一个消费者线程解除阻塞 pthread_cond_signal(&cond); //防止生产过快而死 sleep(rand() % 3); } pthread_exit(NULL); } void *consumer(void *args) { NODE *pNode = NULL; int n = *(int *)args; while (1) { //加锁 pthread_mutex_lock(&mutex); if (head == NULL) { //若条件不满足,则阻塞等待并解锁 //若条件满足(被生产者线程调用pthread_cond_signal函数通知),则加锁该线程解除阻塞。 pthread_cond_wait(&cond, &mutex); } if (head == NULL) { //这里是由于生产者端pthread_cond_signal激活多个消费端 //但是若只有一个数据,第一个释放后,第二个再访问该head则会空则访问失误。 //因此加一个判断,则去掉。 //这里的解锁是由于之前激活时已经取消阻塞,并加锁,因此不解锁,则会导致死锁。 pthread_mutex_unlock(&mutex); continue; } printf("C[%d]:[%d]\n", n, head->data); pNode = head; head = head->next; len--; //解锁 pthread_mutex_unlock(&mutex); //释放该节点内存 free(pNode); pNode = NULL; sleep(rand() % 3); } pthread_exit(NULL); } int main() { int ret; int arr[5]; pthread_t thread1[5]; pthread_t thread2[5]; //随机数种子 srand(time(NULL)); //互斥锁初始化 pthread_mutex_init(&mutex, NULL); //条件变量初始化 pthread_cond_init(&cond, NULL); for (int i = 0; i < 5; i++) { arr[i] = i; ret = pthread_create(&thread1[i], NULL, producer, &arr[i]); if (ret != 0) { printf("pthread[%d]_create error, [%s]\n", i, strerror(ret)); return -1; } ret = pthread_create(&thread2[i], NULL, consumer, &arr[i]); if (ret != 0) { printf("pthread[%d]_create error, [%s]\n", i, strerror(ret)); return -1; } } for (size_t i = 0; i < 5; i++) { //等待线程结束 pthread_join(thread1[i], NULL); pthread_join(thread2[i], NULL); } //释放互斥锁 pthread_mutex_destroy(&mutex); //释放条件变量 pthread_cond_destroy(&cond); return 0; }
信号量相当于多把锁, 可以理解为是加强版的互斥锁
/************************************************************************************* * @Descripttion : sem_t信号量模拟多线程生产者消费者模型。 * @version : 1.0 * @Author : liuziyan * @Date : 2021-07-26 14:58:53 * @LastEditors : Lzy * @LastEditTime : 2021-07-26 15:07:40 * @FilePath : /day9/pthread_sem2.c * @Copyright 2021 liuziyan, All Rights Reserved. *************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h> typedef struct node { int data; struct node *next; } NODE; NODE *head = NULL; //链表长度 int len = 0; //定义生产者和消费者信号 sem_t sem_producer; sem_t sem_consumer; //生产者模型(头插法生成链表) void *producer(void *args) { NODE *pNode = NULL; while (1) { //生产一个节点 pNode = (NODE *)malloc(sizeof(NODE)); if (pNode == NULL) { perror("malloc error:"); exit(-1); } //加锁 相当于生产者-- sem_wait(&sem_producer); len++; pNode->data = len; printf("P[%d]:[%d]\n", *(int *)args,pNode->data); pNode->next = head; head = pNode; //解锁 相当于消费者++ sem_post(&sem_consumer); //防止生产过快而死 sleep(rand() % 3); } pthread_exit(NULL); } void *consumer(void *args) { NODE *pNode = NULL; while (1) { //加锁 sem_wait(&sem_consumer); printf("C[%d]:[%d]\n", *(int *)args,head->data); pNode = head; head = head->next; len--; //解锁 生产者 sem_post(&sem_producer); //释放该节点内存 free(pNode); pNode = NULL; sleep(rand() % 3); } pthread_exit(NULL); } int main() { int ret; int arr[5]; pthread_t thread1[5]; pthread_t thread2[4]; //随机数种子 srand(time(NULL)); //int sem_init(sem_t *sem, int pshared, unsigned int value); sem_init(&sem_producer,0,5); sem_init(&sem_consumer,0,0); for (int i = 0; i < 5; i++) { arr[i] = i; ret = pthread_create(&thread1[i], NULL, producer, &arr[i]); if (ret != 0) { printf("pthread_create error, [%s]\n", strerror(ret)); return -1; } } for (int i = 0; i < 4; i++) { arr[i] = i; ret = pthread_create(&thread2[i], NULL, consumer, &arr[i]); if (ret != 0) { printf("pthread_create error, [%s]\n", strerror(ret)); return -1; } } //等待线程结束 for (int i = 0; i < 5; i++) { pthread_join(thread1[i], NULL); } for (size_t i = 0; i < 4; i++) { pthread_join(thread2[i], NULL); } //释放信号量资源 sem_destroy(&sem_producer); sem_destroy(&sem_consumer); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。