This commit is contained in:
1AoB 2024-04-21 16:18:20 +08:00
parent 45762d8956
commit 530e4627d0
2 changed files with 65 additions and 0 deletions

View File

@ -246,6 +246,71 @@ auto_ptr是C++98中引入的第一个智能指针但是由于他的不安全
加锁:**互斥锁**,**读写锁**,cpp中特有的智能锁
死锁;
- 产生的条件:互斥,请求保存,不可抢占,循环等待
- 可能产生的情况分为两种:
1)第一种是:用到了一把锁造成的死锁,产生的原因是操作失误,加了锁后忘记解锁了
或者是一把锁被加了两次造成的死锁,你再去解锁就解不开了…
或者是你在解锁之前因为满足某种条件提前return了
```
eg
void func{
上锁
if条件return;
解锁
}
```
说是忘记但有时候就是容易但这样的错误而且在项目开发的时候调试起来没那么容易比如说我们最容易犯的函数循环嵌套的死锁问题函数a调用了函数b但是函数a和b内部都用到了同一把锁保护相同的共享资源导致一个线程同时上两次锁这个问题还是比较隐晦的我遇到过一次
2)另一种是用到了多把锁,
当多个线程访问了多块共享资源就需要多把锁共享资源可以是一个全局变量也可能是一段堆内存还可能是一个静态资源或者是在main函数中申请的一段栈空间因为只要main函数不结束这个资源就不会被回收所以也可以做这个共享资源所以说每个共享资源都需要一把锁。
比如说两个共享资源两把锁资源x被锁a锁住了资源y被锁b锁住了在资源x没有解锁的情况下资源x去访问资源y而资源y也在没有解锁的情况下去访问资源x这样就僵持不下
- 死锁避免的解决办法:
1. 第一种方法:你在访问其他共享资源时,需要先把你目前持有共享资源解开。
2. 第二种方式:在访问共享资源时,不要直接加锁,而是尝试加锁()因为我们提供的互斥锁里面都有一个trylock如果尝试失败你就先等一等等其他线程解锁后你再trylock就成功了
3. 另外cpp11还提供了lock_guard智能锁和智能指针管理类似使用了lock_guard我们就不需要去维护互斥锁的解锁操作。不过lock_guard管理的是一个大括号这一段代码假如说这段大括号有100多行代码使用lock_guard就不太划算因为锁住的太多了这个使用还是使用常规锁不要使用智能锁。
---
在项目中,我使用的是libevent+线程池,在线程池中有很多子线程,如果有子线程操作共享资源,那么需要加锁,
这里也是会有一个生产者消费者的概念,任务队列相当于那个容器,不断有生产者线程给任务队列中放任务,也不断有消费者线程从任务队列里面拿任务,生产者线程不只一个,消费者线程也不只一个.
<font color=red>如果只有一个任务队列,会出现惊群效应</font>:只有一个任务可拿,但是却唤醒了所有的消费者线程,最后只有一人能够拿到这个任务,其他消费者都是无效唤醒
为了解决这个"惊群效应",我们采用建立多个任务队(有多少个线程,就创建多少个任务队列),每个线程都有属于自己的任务队列,那么此时就不再出现线程与线程之间的竞争了(就和libevent+线程池一样,每个线程都有属于自己的事件集合,为的就是避免线程竞争),既然该任务队列被一个线程独占,那么就不存在竞争了,就无需加锁,他在添加的时候不能处理,他在处理的时候不能添加
主线程负责两件事:
1)负责和新客户端建立连接
2)主线程还会给任务队列中添加任务,子线程负责从任务队列中取任务
---
有一个很傻的问题:
## 13.死锁
死锁产生的条件:

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB