博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
操作系统之进程互斥的经典问题的分析
阅读量:7189 次
发布时间:2019-06-29

本文共 3614 字,大约阅读时间需要 12 分钟。

基础了解的信息


铺垫是关于使用mutex作为锁实现的核心,那就是原子操作P(wait)和V(singal)的作用及含义。

- P是操作就是使得信号量Semophore的数量减一,当然了前提是信号量的大小是大于0的,如果小于等于0,此进程就会阻塞在该信号量的等待队列上面,只有等待来自另外的进程的唤醒信息来唤醒它。
- V操作就是使得信号量的数量加一,而在此处信号量的如果是小于0的,那么这个数的值就是该信号量的等待队列的进程的数目。

在进行对信号量的操作的核心就是,只有P和V操作可以对信号量进行加减,其他操作没有此权限。

生产者消费者问题:


  • 首先是考虑生产者和消费者只有一对一,且仓库的容量也只有一的状况:

    生产者将生产的产品放入到仓库中。那么我们不难想象只有在仓库中有产品的时候,消费者才能消费;只有仓库存在空位的时候,生产者才能将生产的产品放入到仓库。此时,对于生产者而言仓库为empty就是它的资源,对于消费者而言,仓库为full就是它的资源。

    //对于生产者while(true){    //生产产品    p(empty);    //将产品放入到仓库    v(full);}--------------------------------------------------------------------------------------//对于消费者while(true){    p(full);    //消费产品    v(empty);}
  • 现在考虑第二个阶段,那就是现实中仓库的容量n一般来说都是远远大于1的,那么情况会变成什么样呢?

    经过老师指导,使用环形缓冲原理就可以实现对仓库的良好的访问,而且效率也很高。

//对于生产者    i = 0;    while(true){        //生产产品        p(empty);        //将产品放入到仓库        i = (i+1) % n ;        v(full);    }    --------------------------------------------------------------------------------------//对于消费者    j = 0;    while(true){        p(full);        //消费产品        j = (j + 1 ) % n ;        v(empty);    }
  • 再回到现实中,往往一个仓库中产品是由好几家工厂来生产的,那么在向仓库中添加产品的时候不可避免的会发生冲突,这个时候添加一个锁机制是很有必要的,否则就有可能导致两家工厂添加产品的时候出现错误;同样对于消费者也应该进行同样的处理。
/对于生产者    i = 0;    while(true){        //生产产品        p(empty);        p(mutex);        //将产品放入到仓库        i = (i+1) % n ;        v(mutex);        v(full);    }    --------------------------------------------------------------------------------------//对于消费者    j = 0;    while(true){        p(full);        p(mutex);        //消费产品        j = (j + 1 ) % n ;        v(mutex);        v(empty);    }

读者写者问题


对于这个经典的问题,我们需要了解的是读者与写者都是对于同一个Shared Data进行访问的,所以就有可能出现下面的几种情况。

1、读操作可以同时进行(R-R)2、读操作和写操作不可以同时进行(R-W,互斥)3、写操作和写操作不可以同时进行(W-W,互斥)

因此,我们需要谨慎的进行处理了。

- 下面是第一种我们可能想到的最朴素的想法。那就是加锁,不论三七二十一,双方都进行加锁,这样就不会出现上面的2,3问题了。但是却违背了1的问题,因为RR是可以并发的。

//对于读者     while(true){        p(mutex);        //读取数据        v(mutex);     }-----------------------------------------------------------------------------------------------//对于写者     while(true){        p(mutex);        //写入数据        v(mutex);     }
  • 所以我们要对读者进程进行进一步的修改。
while (true)  {         P(r_mutex);         r_cnt++;         if(r_cnt==1)  P(mutex);         V(r_mutex);         read();         P(r_mutex);         r_cnt- -;         if(r_cnt==0) V(mutex);         V(r_mutex);     }

其中,里面的核心处理就在于

P(r_mutex);    r_cnt++;    if(r_cnt==1)  P(mutex);    V(r_mutex);

是对于r_cnt数量的修改时互斥的保证。实现的功能就是在所有读者中只允许有一个读者获得锁,这样便可以满足1,2,3的要求了。但是这并不是最完美的解决方案,因为有可能读者数量会很大很大,而写者根本没时间写入数据,导致“死等”的情况出现。因此我们还得进行进一步的改进措施。

  • 添加限制条件,即当写者获得锁的时候,所有读者进程将会阻塞。
//核心就在于rw_mutex信号量的掌控上    //读者    while (true)  {         P(rw_mutex);         P(r_mutex);         r_cnt++;         if(r_cnt==1)  P(mutex);         V(r_mutex);         V(rw_mutex);         read();         P(r_mutex);         r_cnt- -;         if(r_cnt==0) V(mutex);         V(r_mutex);    }    //写者    while (true)  {        P(rw_mutex);        P(mutex);        write();        V(mutex);        V(rw_mutex);    }

哲学家吃米饭问题


rice.png

简单的介绍就是,哲学家竞争吃米饭,但是前提是拥有两只筷子。对于哲学家来说,筷子就是他们竞争的资源,现在的问题就是如何解决这一个互斥问题。
正常来讲,如果一个哲学家获得了一双筷子,那么旁边的哲学家就需要等待筷子的释放,之后才能获得资源。

do{           wait ( chopstick[i] );         wait ( chopStick[ (i + 1) % 5] );                 //  eat         signal ( chopstick[i] );         signal (chopstick[ (i + 1) % 5] );                 //  think    } while (TRUE);

但是这样会存在一个问题,那就是“死锁”,比如每个哲学家都拿到了一只筷子,那么整个代码就会处于Deadlock的处境。那么怎样才能解决这个问题呢?

下面是我自己的一些理解,可能不正确,欢迎大家批评指正
  • 对于奇数位哲学家,只有偶数位的哲学家可以首先拥有资源,这样就可以去除死锁,但是会有一只筷子剩余,这不符合对资源高效利用的原则;
  • 对于偶数位哲学家,奇数位与偶数位的可以轮流获取资源,这样也可以解决问题。
  • 使用随机的方式,让所有的哲学家随机的获取资源,这样有利有弊,稳定性可能稍微有点不太好。

总结


操作系统课上,胡燕老师幽默的讲课风格让我有了很大的热情来研究这里面的复杂的学问,虽然自己目前而言水平仍然很差,但是我从中收获到了很多。感谢老师!

转载地址:http://tzfkm.baihongyu.com/

你可能感兴趣的文章
UNIX/Linux系统取证之信息采集案例
查看>>
Python知识点总结篇(五)
查看>>
一致性算法探寻(扩展版)1
查看>>
这几个 Chrome 的 Tab 增强插件你都用上了吗?
查看>>
Java中的浅拷贝与深拷贝
查看>>
微信小程序联盟:官方文档+精品教程+demo集合(6月9日更新,持续更新中……)...
查看>>
spring 事务的传播特性
查看>>
react学习(1)-Why React?
查看>>
RESTful风格的API接口开发教程
查看>>
用 Lua 实现一个微型虚拟机-基本篇
查看>>
php 安装 memcached 扩展出现 zlib 错误
查看>>
CentOS中服务程序随系统启动
查看>>
我的友情链接
查看>>
永久关闭selinux
查看>>
zTree 树使用$('#test').load("url"),后树不能使用
查看>>
C文件的编译、链接和运行指令
查看>>
bootstrap Modal的简单笔记
查看>>
统计一串字符串中连续相同元素的个数
查看>>
奋斗例子——>从1.5k到18k, 一个程序员的5年成长之路
查看>>
python2.x之list和tunple及dict
查看>>