死锁:指两个或两个以上进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待现象,若无外力作用,它们都将无法继续推进下去。

例:交叉死锁:线程1获得了锁1,线程2获得了锁2,此时线程1调用lock想获得锁2,需挂起等待线程2释放锁2,而线程2也想获得锁1,也需挂起等待线程1释放锁1,此时两个线程都挂起等待

产生死锁的四个必要条件:

(1):互斥条件(一个资源每次只能被一个进程或线程使用)

(2):请求与保持条件(一个进程或线程因请求资源而阻塞时,对已获得的资源不释放)

(3):不剥夺条件(此进程或线程已获得的资源在未使用完之前,不能强行剥夺)

(4):循环等待条件(多个进程或线程之间互相形成一种头尾相接的循环等待资源关系)

条件变量:当一个线程需要某个条件成立才能继续执行,若不成立则就要挂起等待,若另一个线程在执行过程中使该条件成立,则唤醒第一个线程继续执行。一般需要与互斥锁搭配使用

条件变量的初始化:pthread_cond_init(pthread_cond_t* cond,const pthread_condattr_t* attr);//也可用宏初始化

条件变量的销毁:pthread_cond_destroy(pthread_cond_t* cond)

线程可以调用pthread_cond_wait在条件变量中阻塞等待(当无数据消费时,让消费者阻塞等待),可用pthread_cond_signal唤醒(当生产者生产出数据时,唤醒消费者进行消费)

生产者-消费者模型满足以下要素:

三种关系:消费者与消费者、生产者与生产者之间互斥,生产者与消费者之间同步与互斥

两中角色:生产者、消费者

一个场所:使用链表

生产者在链表头上生产数据,消费者在头上消费数据(后进先出)

wKiom1cd8RnQoFnQAABapIzI9jU201.png

wKiom1cd8RqAOrE1AABaiuQhb2Y729.png

wKiom1cd8Rrh1PcSAABcDh9rT4g022.png

wKiom1cd8SGDSgF1AAAzuhv2CkI028.png


信号量(POSIX版本):表示可用资源的数量,类似与mutex互斥量,初始mutex为1,表示有一个资源可用,加锁时获得该资源,Mutex减为0,表示无可用资源,但信号量的数目可以大于1;

信号量的有关函数:

int sem_init(sem_t* sem,int pshared,unsigned int val);//初始化多少个信号量为什么值

int sem_wait(sem_t* sem);//进行P操作;即申请资源

int sem_post(sem_t* sem);//进行V操作,释放资源

int sem_destroy(sem_t *sem);使用完semaphore变量资源后释放资源

中间场所:使用环形缓冲区(用数组下表模拟实现)

以生产者-消费者为例:对于生产者来说只关心有多少个空间可以生产,对于消费者关心有多少个有效数据可以消费,必须保证消费者不能 超过生产者,同时生产者不能将消费者套圈

定义两个semaphore变量,一个为格子数,一个为数据

wKioL1cd9pvTrfWgAABdMzL_yIY495.png

wKioL1cd9pvDJkU6AABS3Re32ZQ696.png

wKioL1cd9pyxJuvIAAA9gn86XVY615.png

当生产者生产数据慢,而消费者生产数据快时:

wKiom1cd9jbQohENAAA6Uqt9gKM169.png

wKiom1cd9jfCd9JoAABUpVkEfFg522.png

当生产者生产数据快消费慢时:

wKioL1cd9v_wacpNAAA9q3NRsA4389.png


wKioL1cd9zTiOYS_AABUpVkEfFg560.png

多生产者多消费者模型:满足多个消费者之间互斥,多个生产者互斥,分别给消费者和生产者中互斥加锁

wKioL1ceB6qAI_-9AABXDggmGuQ771.png

wKioL1ceB6qiEEJ1AABILv9Egis937.png

wKiom1ceBwOSogJSAABKpFrXi9U245.png