信号量和管程

简介: 信号量和管程

信号量和管程


信号量


抽象数据类型:


  • 一个整形(sem),两个原子操作


P:sem减一,如果sem<0则等待,否则继续

V:sem加一,如果sem<=0唤醒一个等待的P


  • 信号量是证书


  • 信号量是被保护的变量


初始化完成之后,唯一改变一个信号量的值的办法是通过P()和V()

操作必须是原子的


  • P()能够阻塞,V()不会阻塞


信号量的使用


  • 两种类型信号量

二进制信号量:可以是0或者1

一般/计数信号量:可以取任何非负值

两者互相表现(给定一个可以实现另外一个)


  • 信号量可以在2个方面使用

互斥

条件同步


例子:


  • 一个线程等待另外一个线程处理事情

比如生产东西和消费东西

互斥是不够的


使用约束


  • 正确性要求

在任何一个时间只能由一个线程操作缓冲区

当缓冲区为空,消费者必须等待生产者

当缓冲区满时,生产者必须等待消费者


  • 上面对应的每个约束用一个单独的信号量

二进制信号量,互斥

一般信号量

一般信号量


信号量的实现


使用操作系统的等待队列,使得不满足信号量的情况下,睡眠


  • 信号量的双用途

互斥和条件同步

等待条件是独立的互斥


  • 读、开发代码比较困难

程序员必须非常精通信号量


  • 容易出错

使用信号量已经被另一个线程占用

忘记释放信号量


  • 不能够处理死锁问题


管程


  • 目的:分离互斥和条件同步的关注


  • 什么是管程:

一个锁:指定临界区

0或者多个条件变量:等待/通知信号量用于管理并发访问共享数据


  • 一般方法

手机在对象/模块中的相关共享数据

定义方法来访问共享数据


经典同步问题


读者-写者问题


  • 动机

共享数据访问


  • 两种类型使用者

读者:不需要修改数据

写者:读取和修改数据


  • 问题约束

允许同一时间有多个读者,但在任何时候只有一个写者

当没有写者时,读者才能访问

当没有读者和写者时,写者才能访问数据

在任何时候只有一个线程可以操作共享变量


  • 多个并发线程的数据集共享

读者:只读数据集,他们不执行任何更新

写者:可以读取和写入


  • 共享数据

数据集

信号量countmutex初始化为1

信号量writemutex初始化为1

整数rcount初始化为0


基于读者有限策略的方法,只要有一个读者处于活动状态,后来的读者都会被接纳。如果读者源源不断的出现的话,那么写者就会始终处于阻塞状态。


基于写者优先的策略的方法:一旦写者就绪,那么写者会尽可能快的执行写操作,如果写者源源不断的出现的话,那么读者就始终处于阻塞状态。


哲学家就餐问题


5个哲学家围绕一张圆桌而坐,桌子上放着5个叉子,每两个哲学家之间放一个;哲学家的动作包括思考和进餐,进餐时需要同时拿起左边和右边的两个叉子,思考时候需要把叉子放回原处。如何保证哲学家们动作有序进行?


  • 必须有一个数据结构描述每个哲学家的状态
  • 该状态是一个临界资源,对它的访问应该互斥的进行
  • 一个哲学家吃饱之后,可能要唤醒邻居,存在着同步关系


目录
相关文章
|
安全
理解信号量
理解信号量
|
7月前
|
安全 C++
线程同步:互斥与条件变量
线程同步:互斥与条件变量
|
7月前
|
安全 Linux 调度
【linux线程(二)】线程互斥与线程同步
【linux线程(二)】线程互斥与线程同步
|
7月前
|
Linux
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
200 0
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
|
7月前
|
前端开发 安全 C++
c++11线程、互斥量、条件变量等
c++11线程、互斥量、条件变量等
|
7月前
多线程并发之Semaphore(信号量)使用详解
多线程并发之Semaphore(信号量)使用详解
2331 0
|
算法
信号量(上)
信号量(上)
38 0
|
存储
信号量(下)
信号量(下)
43 0
|
机器学习/深度学习 C语言
信号量
信号量
90 0
|
程序员 调度
信号量和管程
信号量和管程
61 0