记录型信号量实现进程同步、互斥.单类生产者消费者.以进程同步为主互斥为辅的问题

1.问题描述

Q1:为何设置两个用于同步的信号量

Q2:为何互斥进行的是生产者的MoveStuffToBuffer();消费者的RemoveStuffFromBuffer(); 

Q3:为何P(stuff)为生产者进程的第一个代码

2.问题分析

3.反思与总结

        为什么开始需要P操作,为什么需要两个信号量......这些问题很多都是由于我们使用记录型信号量机制这种管理策略去对并发的进程进行管理,以达到将这些并发进程有序(同步)、独立(互斥)地访问一些资源的目的,为了实现这些目的,我们想到了某些情况下可以让进程sleep(),某些情况下可以让进程wake(唤醒进程),而我们怎么知道什么时候进程需要进行sleep,什么时候进程需要被wake()?

        对于计算机而言我们可以赋予数字一些实际含义(例如将实际资源数目映射到相应数字),通过这些映射的数字来代表一种信号,使用信号反馈于多个进程,这种信号所反馈的信息可以用来检测判断是否需要将进程sleep(进入阻塞态)或者wake(转为就绪态)进而对进程进行控制,这种信号可以看做是控制信号,可以将信号与一个恒定量进行比较来决策是否需要对进程进行sleep或wake信号中的sleep的进程。但是这种管理策略是具有约束的,这些约束就是:我们只能通过判断控制信号是否小于0来确定进程是否应该被阻塞入控制信号所代表的相应资源的阻塞队列只能那个通过判断控制信号是否大于等于0来确定是否将由于控制信号所代表的相应资源存在了而将陷入相应资源等待队列中的进程唤醒。进一步说,控制信号就是semaphore s 的 s.value; 控制信号(数值)就是实际资源映射的相应数字,对于P内操作执行s.value-1后,如果s.value<0 ,s所代表的资源的阻塞队列(等待使用资源的进程)会增加一个执行此P操作的进程,这也就解释了为什么当s.value为负值时其绝对值代表等待进程数量. 这也解释了记录型信号量为什么不⇔控制信号,记录型信号量不仅包含所记录的控制信号,还包含记录型信号量代表的相应的资源中等待使用相应资源的阻塞队列,这个队列存放着想要使用该资源的进程,记录型信号量机制是通过控制信号反馈于操作sleep当前进程和wake信号量的阻塞队列来控制进程的。

对上文的小结:

        semaphore s;//s ⇔ 系统资源

        s.value;// ⇔ 控制信号

        s.queue//⇔ 等待使用相应资源的阻塞队列

        P操作与 (信号量-1)和(阻塞进程)绑定在一起,V操作与(信号量+1)和(进程唤醒)绑 定在一起。即:P(S) V(S) 通过调节控制信号反馈作用于是否wake(s.queue)和sleep(this_process)。

        这种通过控制信号代表的资源数目来反馈控制进程的机制就是通过对s.value++ 和 s.value--来完成,信号量的s.value++和if(s.value <0) EnqueueThisProcess(s.queue); sleep(this_porcess);

绑定在一起,信号量的s.value--和if(s.value <=0) DequeueProcess(s.queue); wake(this_porcess);

绑定在一起,PV操作具有原子性,故我们不可以任意的进行P V,其代表的信号操作、信号反馈判断条件和反馈操作含义已经绑定。

        同样的,我们只能对信号量的操作也具有约束,只能进行三种操作,其分别是作分别是:

        (1)   对信号量进行初始化(并且不能为负值)

        (2)对信号量进行P(s)操作,会完成s.value--; if(s.valuie < 0){ EnqueueThisProcess(s);         sleep(ThisProcess); }

        (3)   对信号量进行V(s)操作,会完成s.value++; if(s.valuie <= 0){ DequeueTheProcess(s);         wake(TheProcess); } 

        由此约束才有了对于信号量控制进程的分析基本的法则,就像数学中的下定义,其实DJ大佬提出的信号量机制控制进程也是具有其定义的,也就是控制进程来同步互斥的控制的规则。并且具有较强的约束性,我想这也是为什么可以对多进程同步和互斥行管理使其有序的一个原因吧。

笔者思考深度有限,若有问题欢迎讨论!恳请愿各路大神指点!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程记录信号量是一种用于解决进程同步问题的机制,可以用来解决生产者消费者问题。在这个问题中,生产者和消费者共享一个缓冲区,生产者不断向缓冲区中添加产品,消费者从缓冲区中消费产品。为了保证生产者和消费者之间的同步,需要使用三个信号量:mutex、full、empty。 其中,mutex是一个二进制信号量,用于保护缓冲区的互斥访问。当一个进程正在访问缓冲区时,其他进程必须等待。full和empty是计数信号量,分别表示缓冲区中已有的产品数量和空闲的缓冲区数量。 生产者在向缓冲区中添加产品之前,必须先获取empty信号量,如果缓冲区已满,则生产者必须等待。当生产者成功向缓冲区中添加了一个产品后,需要释放mutex信号量,并增加full信号量的计数值。 消费者在从缓冲区中消费产品之前,必须先获取full信号量,如果缓冲区为空,则消费者必须等待。当消费者成功从缓冲区中消费了一个产品后,需要释放mutex信号量,并增加empty信号量的计数值。 下面是一个使用进程记录信号量解决生产者消费者问题的C语言实现的伪代码: ``` #define N 100 // 缓冲区大小 int buffer[N]; // 缓冲区 int in = 0; // 生产者向缓冲区中添加产品的位置 int out = 0; // 消费者从缓冲区中消费产品的位置 sem_t mutex, full, empty; // 三个信号量 void producer() { while (true) { int item = produce_item(); // 生产一个产品 sem_wait(&empty); // 等待空闲的缓冲区 sem_wait(&mutex); // 获取互斥访问权 buffer[in] = item; // 将产品添加到缓冲区中 in = (in + 1) % N; // 更新in指针 sem_post(&mutex); // 释放互斥访问权 sem_post(&full); // 增加缓冲区中产品的数量 } } void consumer() { while (true) { sem_wait(&full); // 等待缓冲区中有产品 sem_wait(&mutex); // 获取互斥访问权 int item = buffer[out]; // 从缓冲区中取出一个产品 out = (out + 1) % N; // 更新out指针 sem_post(&mutex); // 释放互斥访问权 sem_post(&empty); // 增加空闲的缓冲区数量 consume_item(item); // 消费产品 } } int main() { sem_init(&mutex, 0, 1); // 初始化mutex信号量为1 sem_init(&full, 0, 0); // 初始化full信号量为0 sem_init(&empty, 0, N); // 初始化empty信号量为N // 创建生产者和消费者线程 pthread_t producer_thread, consumer_thread; pthread_create(&producer_thread, NULL, producer, NULL); pthread_create(&consumer_thread, NULL, consumer, NULL); // 等待线程结束 pthread_join(producer_thread, NULL); pthread_join(consumer_thread, NULL); return 0; } --相关问题--:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值