一、读写锁
有些公共数据修改的机会很少,但其读的机会很多。并且在读的过程中会伴随着查找,给这种代码加锁会降低我们的程序效率。读写锁可以解决这个问题。
读写锁本质上是一种自旋锁

读者——写者:同步与互斥
写者——写者:互斥
读者——读者:共享、没关系
面试题:为什么消费者与消费者之间是互斥而读者与读者之间是没关系?
因为消费者会将数据拿走,而读者只访问不会将数据拿走
注意:写独占,读共享,写锁优先级高
读写锁的策略:读者优先
写者优先
初始化

读写锁的属性一般设置为空
销毁

加锁和解锁

1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5
6 int counter;//计数器
7 pthread_rwlock_t rwlock;//读写锁
8
9 void* route_write(void *arg)
10 {
11 int no = (int)arg;
12 while(1){
13 int t = counter;
14 pthread_rwlock_wrlock(&rwlock);//加写锁
15 printf("write:thread(%d) id :%x inc %d to %d\n",no,pthread_self(),t,++counter);
16 pthread_rwlock_unlock(&rwlock);//解锁
17 sleep(2);
18 }
19 }
20
21 void* route_read(void *arg)
22 {
23 int no = (int)arg;
24 while(1){
25 pthread_rwlock_rdlock(&rwlock);//加读锁
26 printf("reader:thread(%d) id:%x data is : %d\n",no,pthread_self(),counter);
27 pthread_rwlock_unlock(&rwlock);//解锁
28 sleep(1);
29 }
30 }
31
32 int main()
33 {
34 int i;
35 pthread_t tid[8];
36
37 pthread_rwlock_init(&rwlock,NULL);
38
39 for(i = 0;i < 3;i++)//创建3个写者线程
40 {
41 int *p = (int*)malloc(sizeof(int));
42 *p = i;
43 pthread_create(tid+i,NULL,route_write,(void*)p);
44 }
45 for(i = 3;i < 8;i++)//创建5个读者线程
46 {
47 int *p = (int*)malloc(sizeof(int));
48 *p = i;
49 pthread_create(tid+i,NULL,route_read,(void*)p);
50 }
51 for(i = 0;i < 8;i++)
52 {
53 pthread_join(tid[i],NULL);
54 }
55 pthread_rwlock_destroy(&rwlock);
56 }

二、死锁
死锁是指多个线程因竞争资源而造成的僵局(互相等待)
1、产生死锁的4个条件:
a、互斥:某资源只能被一个进程使用,其他进程请求该资源时,只能等待,直到该资源被使用完毕
b、请求和保持条件:程序已经保持了至少一个资源,但是又提出了新要求,而这个资源被其他进程占用,自己占用的资源却保持不放
c、不可抢占条件:进程已获得的资源没有使用完,不能被抢占
d、循环等待条件:必然存在一个循环链
2、处理死锁的方法:
a、预防死锁:破坏死锁的四个必要条件中的任何一个或多个
b、避免死锁:和预防死锁的区别是,在资源动态分配过程中,用某种方式防止系统进入不安全的状态
c、检测死锁:运行时出现死锁,能及时发现死锁,把程序解脱
d、解除死锁:发生死锁后,解脱进程,通常撤销进程,回收资源,再分配给正处于阻塞状态的进程
3、预防死锁的方法:
a、破坏请求和保持条件
b、破坏不可抢占条件
c、破坏循环等待条件
4、避免死锁的方法:
a、加锁顺序
b、加锁时限
c、死锁检测
本文探讨了读写锁的概念,强调了读写锁在处理频繁读取但很少修改的数据时的优势,以及读写锁的策略:读者优先和写者优先。同时,解释了为何读者之间不需要互斥。接着,文章深入讲解了死锁的定义,阐述了产生死锁的四个必要条件,并列举了处理死锁的四种方法,包括预防、避免、检测和解除死锁的策略。

2521

被折叠的 条评论
为什么被折叠?



