【Linux】利用 <信号量> 实现 <生产者-消费者模型-线程同步 >(思维导图&代码演示&思路解析)

前言

大家好吖,欢迎来到 YY 滴Linux系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁
主要内容含:
在这里插入图片描述

欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!

一.什么是生产者消费者模型

生产者消费者问题(Producer-Consumer Problem)通常用于多线程编程中的线程间通信和同步。

  1. 该问题描述了两个线程(或进程)之间的协作: 一个或多个生产者线程生成数据项,并将它们放入 缓冲区 ;一个或多个消费者线程从 缓冲区 取出数据项,并进行处理。
  2. 这个过程中,生产者和消费者需要同步,以避免竞争条件和资源冲突。

二.生产者和消费者各只有一人,缓冲区单元只有一个,用P、V原语实现生产者和消费者的同步操作

题目:

  • 对于生产者-消费者问题,若缓冲区中缓冲区单元只有一个,生产者和消费者各只有一人。用P、V原语实现生产者和消费者的同步操作

解析:

  1. 设置两个信号量,empty full
  2. 生产者会等待empty,等待缓冲区为空
  3. 消费者会等待full,等待缓冲区满
  4. 一开始缓冲区是空的,所以设置时,empty=1,先进去;Semaphore empty = 1; Semaphore full = 0;
  5. 生产者线程和消费者线程, 彼此互相唤醒对方的信号量 ,即可

流程图演示:
1

// 信号量初始化  
Semaphore empty = 1;  // 缓冲区空闲单元数量  
Semaphore full = 0;   // 缓冲区已占用单元数量  

Buffer buffer;  // 缓冲区

// 生产者线程  
void producer() {
    
      
	    while (true) {
    
      
	        // 生产一个数据项  
	        item = produceItem();   
	        
            // 等待缓冲区有空闲单元  
	        P(empty);  

	        // 将数据项放入缓冲区  
	        buffer = item;  
 
	        // 通知消费者缓冲区中有数据  
	        V(full);  
	        }  
}  
// 消费者线程  
void consumer() {
    
      
	    while (true) {
    
      
	        // 等待缓冲区有数据  
	        P(full);  
 
	        // 从缓冲区中取出数据项  
	        item = buffer;  

           // 通知生产者缓冲区中有一个空闲单元  
	        V(empty);  
	  
           // 消费数据项  
	        consumeItem(item);  
	    }  
}

三.生产者和消费者各只有一人,缓冲区单元有n个,用P、V原语实现生产者和消费者的同步操作

题目:

  • 对于生产者-消费者问题,若缓冲区中缓冲区的单元有n个,生产者和消费者各只有一个。用P、V原语实现生产者和消费者同步操作。

主干部分解析:

  1. 设置两个信号量,empty full
  2. 生产者会等待empty,等待缓冲区为空
  3. 消费者会等待full,等待缓冲区满
  4. 一开始缓冲区是空的,所以设置时,empty=1,先进去;Semaphore empty = 1; Semaphore full = 0;
  5. 生产者线程和消费者线程, 彼此互相唤醒对方的信号量 ,即可

改动部分解析:

  1. 缓冲区单元有n个,所以用 数组 的形式表示缓冲区,Buffer[n] buffer;
  2. 设置两个索引in out
  3. in 给生产者使用,表示指向下一个空闲缓冲区的索引
  4. out 给消费者使用,表示指向下一个有数据缓冲区的索引
  5. 其中,小算法(in/out+1)%n 实现了循环

流程图演示:
在这里插入图片描述

// 信号量初始化  
Semaphore empty = n;  // 缓冲区空闲单元数量,初始为n 
Semaphore full = 0;   // 缓冲区已占用单元数量  

Buffer[n] buffer;     // 大小为n的缓冲区数组  
int in = 0;           // 指向下一个空闲缓冲区的索引(生产者使用)  
int out = 0;          // 指向下一个有数据缓冲区的索引(消费者使用)  

// 生产者线程  
void producer() {
    
      
	    while (true) {
    
      
	        // 生产一个数据项  
	        item = produceItem();   
	        
            // 等待缓冲区有空闲单元  
	        P(empty);  

            // 将数据项放入缓冲区
 	        buffer[in] = item;  
	        in = (in + 1) % n;  // 循环使用缓冲区  
	        
	        // 通知消费者缓冲区中有数据  
	        V(full);  
	        }  
}  
// 消费者线程  
void consumer() {
    
      
	    while (true) {
    
      
	        // 等待缓冲区有数据  
	        P(full);  
 
	        // 从缓冲区中取出数据项  
	        item = buffer[out];  
	        out = (out + 1) % n;  // 循环使用缓冲区
	        
           // 通知生产者缓冲区中有一个空闲单元  
	        V(empty);  
	  
           // 消费数据项  
	        consumeItem(item);  
	    }  
}

猜你喜欢

转载自blog.csdn.net/YYDsis/article/details/143453543