首页 > 其他分享 >锁—信号量与管程

锁—信号量与管程

时间:2023-11-25 16:47:15浏览次数:28  
标签:notEmpty 队列 lock 管程 信号量 线程 等待

1.基本概念

  1. 互斥
    只有一个线程能访问临界区。

  2. 临界资源
    多个线程可以共享系统中的资源,但是临界资源只允许一个线程在某一时刻访问。如某些变量、硬件资源。

  3. 临界区
    访问临界资源的代码即临界区。

2.信号量与管程

管程(Monitors)和信号量(Semaphores)是操作系统中用于实现并发编程的两种重要技术。

2.1 信号量

2.1.1 定义

操作系统提供的一种协调共享资源访问的方法,优先级高于进程,可以保证原子性。

信号中包括一个整形变量,和两个原子操作 P 和 V。其原子性由操作系统保证,这个整形变量只能通过 P 操作和 V 操作改变。

  • P(Prolaag,荷兰语尝试减少):信号量值减 1,如果信号量值小于 0,则说明资源不够用的,把进程加入等待队列。

  • V (Verhoog,荷兰语增加):信号量值加 1,如果信号量值小于等于 0,则说明等待队列里有进程,那么唤醒一个等待进程。

共享变量S只能由 PV 操作,PV的原子性由操作系统保证。
P相当获取锁,可能会阻塞线程;V相当于释放锁,不会阻塞线程。
根据同步队列中唤醒线程的先后顺序,可以分为公平和非公平两种。

信号量分类:

  • 二进制信号量:资源数目为 0 或 1。
  • 资源信号量:资源数目为任何非负值

2.1.2 例子

实现生产者消费者针对同一队列进行通信,任一时刻只有一个线程在操作队列。

假设只有一个生产者,n个消费者,那么需要三个信号量:

notFull: 表示队列不满,可以推送消息
notEmpty: 表示队列不空,可以消费消息
mutex: 表示互斥,限制同时只有一个线程访问

class Queue {

	private Semaphore notFull = new Semaphore(1);

	private Semaphore notEmpty = new Semaphore(n);

	private Semaphore mutex = new Semaphore(1);

	publib void produce() {
		notFull.P();  //队列不满才能推送,否则等待
		mutex.P();
		//生产消息加入队列
		mutex.V();
		notEmpty.V(); //唤醒等待消费线程
	}

	publib void consume() {
		notEmpty.P();  //队列不空才能消费,否则等待
		mutex.P();
		//生产消息加入队列
		mutex.V();
		notFull.V(); //唤醒等待生产者线程
	}

}

2.2 管程

2.2.1 定义

管程是为了解决信号量在临界区的PV操作上的配对的麻烦而提出的并发编程方法,使用条件变量等同步机制来实现线程之间的协作。

条件变量:
线程中的一种同步机制,它允许线程等待某个条件成立,与信号量不同。
当条件不满足时,线程将自己加入等待队列,同时释放持有的互斥锁;
当一个线程唤醒一个或多个等待线程时,此时条件不一定为真(虚假唤醒)。

先后出现过三种不同的管程模型,分别是:Hasen 模型、Hoare 模型和 MESA 模型,当前广泛使用的是MESA模型。

MESA模型图示:

2.2.2 MESA模型编程范式

while (条件不满足) {
  wait();
}

MESA模型使用while判断的原因是,wait()是进入了条件变量的等待队列。若被notify()或者notifyAll()唤醒,也只是从条件变量等待队列到了入口等待队列。入口等待队列才是竞争锁的地方,等到此线程实际执行的时候,条件可能又不满足了,需要再次wait()。

2.3.3 例子

实现一个自定的阻塞队列,通过Lock类保证互斥条件,notFull和notEmpty分别表示队列非满及非空的条件变量。

public class BlockedQueue<T>{
  final Lock lock = new ReentrantLock();
  // 条件变量:队列不满
  final Condition notFull = lock.newCondition();
  // 条件变量:队列不空
  final Condition notEmpty = lock.newCondition();

  // 入队
  void enq(T x) {
    lock.lock();
    try {
      while (队列已满){
        // 等待队列不满
        notFull.await();
      }
      // 省略入队操作...
      //入队后,通知可出队
      notEmpty.signal();
    }finally {
      lock.unlock();
    }
  }
  // 出队
  void deq(){
    lock.lock();
    try {
      while (队列已空){
        // 等待队列不空
        notEmpty.await();
      }
      // 省略出队操作...
      //出队后,通知可入队
      notFull.signal();
    }finally {
      lock.unlock();
    }
  }
}

2.3.4 唤醒对比

无论何种情况,尽量使用notifyAll()及signalAll(), 可以避免意想不到的bug。

标签:notEmpty,队列,lock,管程,信号量,线程,等待
From: https://www.cnblogs.com/kiper/p/17855520.html

相关文章

  • C++11 多线程并发 互斥量、条件变量和信号量
    互斥量Classesmutex(C++11)providesbasicmutualexclusionfacility(class)timed_mutex(C++11)providesmutualexclusionfacilitywhichimplementslockingwithatimeout(class)recursive_mutex(C++11)providesmutualexclusionfacili......
  • FreeRTOS深入教程(信号量源码分析)
    (文章目录)前言本篇文章将为大家讲解信号量,源码分析。在FreeRTOS中,信号量的实现基于队列。这种设计的思想是利用队列的特性来实现信号量,因为信号量可以被视为只能存储0或1个元素的特殊队列。在FreeRTOS中,二进制信号量(BinarySemaphore)通常由一个队列和一个计数器组成......
  • iOS信号量造成线程优先级反转
    在并发队列使用信号量会可能会造成线程优先级反转一、在iOS16&XCode14上遇到-使用信号量造成线程优先级反转问题提醒经过查询资料,发现是在XCode14上增加了工具,比如:ThreadPerformanceChecker(XCode14上默认开启的),这个工具会让APP在运行的时候,发现有例如线程优先级反转......
  • FreeRTOS(2):队列、信号量、互斥量
    1、队列 1.1数据传输方法任务之间如何传输数据 数据个数互斥措施阻塞-唤醒全局变量1无无环形缓冲区多个无无队列多个有有队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息。为什么不使用全局变......
  • 10-信号量和管程
    10-信号量和管程背景并发问题:竞争条件(竞态条件)多程序并发存在问题同步多线程共享数据的协调执行包括互斥与条件同步互斥:在同一时间只有一个线程可以执行临界区确保同步正确很难?需要高层次的编程抽象(如:锁)从底层硬件支持编译多程序理念临界区高层次抽象锁硬件支持......
  • 信号量Semaphore的使用
    Semaphore是jdk中提供的用来限制资源可以同时被几个线程访问的工具类,它底层也是用aqs实现的。以现实生活中停车场的例子来举例,一个停车场总的车位数是固定的,@Slf4jpublicclassThreadTest4{publicstaticvoidmain(String[]args){//假设只能停两辆车......
  • 信号量与P、V操作
    对于这类问题,我计算啥的都没问题,就是看图很蒙,偏偏大部分都是看图题,所以就来恶补一下关于这种类型的图片题~1、P和V的各自的含义P操作负责分配资源,没有资源的时候就等着(进入阻塞队列)。V操作负责释放资源,在阻塞队列不为空的时候唤醒某个进程进入临界区2、公用信号量--实现进程间......
  • 信号量解决协调进程同步问题(司机与售票员问题)
    问题描述(在日常生活中司机和售票员的行为动作需要满足一定的规则)分析并发进程的交互点1.首先我们将司机和售票员看成是2个进程,他们需要协调配合完成工作2.我们需要找到进行并发执行过程中的交互点(一个进行肯定要等另一个进程做了才能接着往下做),在这个点上我们需要使用P......
  • 二值信号量实现互斥锁的功能
    信号量Semaphore的值可以理解为是可用资源的数量,当Semaphore=1的时候表明可用资源数为1,这和互斥锁中每次只能有一个进行可以访问临界区是一个意思,所以当Semaphore=1的信号量也可以用来实现互斥锁信号量的PV操作,和互斥锁的lock和unlock操作基本类似。只不过设置状态变成了s--......
  • CyclicBarrier和CountDownLatch有什么区别?Semaphore(信号量)了解吗?
    一、CyclicBarrier和CountDownLatch有什么区别?两者最核心的区别:CountDownLatch是一次性的,而CyclicBarrier则可以多次设置屏障,实现重复利用;CountDownLatch中的各个子线程不可以等待其他线程,只能完成自己的任务;而CyclicBarrier中的各个线程可以等待其他线程二、Semaphore(信号量)Sema......