关于操作系统原理几个经典并发问题总结

读者与写者之读者优先问题

1、如果一个写者进程正在修改数据,别的写者以及任何读者都不能访问该数据
2、当一个读者正在读数据时,另一个读者也需要读数据,应允许第二个读者进入,
   同理第三个及随后更多的读者都被允许进入
3、现在假设一个写者到来,由于写操作是排他的,所以他不能访问数据,需要阻塞等待。
   如果一直都有新的读者陆续到来,写者的写操作将被严重推迟

信号量x 队列1:读者
信号量wsem 队列2:读者和写者
1、某一时刻,队列1中读者正在进行,后续如果有读者跟进,则加入队列1,则队列1中的读
   者全部执行结束后开始执行队列2(执行队列1时,若有写者跟进,则加入队列2)
2、某一时刻,队列1读者全部执行结束,队列2写者执行,后续如果有读者或者写者,都不能
   同时对资源进行操作,执行队列2过程中,跟进的写者放入队列2,第一次跟进的读者放在
   队列2当中,其它的读者全部放在队列1中
3、某一时刻,队列2中读者释放出来开始执行,读者执行结束后开始执行队列1中的读者,
   队列2暂停执行,直到下一次开始。。。

const int readcount = 0; /* 统计读者的个数 */

读者                                       写者
wait(x);				wait(wsem);
readcount = readcount + 1;		写数据;
if(readcount = 1) then wait(wsem);	signal(wsem);
signal(x);
读数据;
wait(x);
readcount = readcount - 1;
if(readcount = 0) then signal(wsem);
signal(x);
读者与写者之写者优先问题

1、当共享数据区被读者占用时,后续紧邻到达的读者可以继续进入,若这时有一个写者来到且阻塞等待,
   则写者后面来的若干读者全部阻塞等待
2、换句话说,只要有一个写者申请写数据,则不在允许新的读者进入读数据,这样,写者只需要等待先于
   它到来的读者完成任务其读数据任务,而不用等待其后来的读者。
3、若写者正在进行,则后加来的写者也会优于读者先执行,只有目前没有了写者要执行时,那么开始执行
   读者,重复之前的操作。

信号量 x,y,z,rsem,wsem : semaphore (:=1);
const readcount = writecount = 0;

reader线程
wait(z); //执行写者线程时,后来的读者线程全部阻塞在z.queue
wait(rsem);
wait(x); //确保readcount正确性 
readcount = readcount + 1;
if(readcount = 1) then wait(wsem)
signal(x);
signal(rsem);
signal(z);
读数据;
wait(x);
readcount = readcount - 1;
if(readcount = 0) then signal(wsem);
signal(x);

writer线程
wait(y);
writecount = writecount + 1;
if(writecount = 1)then wait(resm);
signal(y);
wait(wsem);
写数据;
signal(wsem);
wait(y);
writecount=writecount-1;
if(writecount=0)then signal(rsem);
signal(y);

信号量 关于书上的生产者与消费者问题

s 互斥信号量  s.count = 1; //当前对资源操作只有一个线程
n 资源信号量  数据单元 n.count = 0;
e 资源信号量  空存储单元 e.count = 缓冲区大小;

生产者进程
wait(e); //有了空储存单元
wait(s); //锁定生产者的操作,资源仅限于当前生产者线程使用
存入一条数据; //往空资源存入数据
signal(s);//释放其它生产者或消费者线程  
signal(n);//释放一个可以进行消费的资源, n.count++;

消费者进程
wait(n); //有了消费的数据单元
wait(s); //锁定消费者的操作,资源仅限于当前消费者线城使用
取出一条数据;//留下空资源一个单位
signal(s);//释放其它生产者或消费者线程  
signal(e);//释放空资源

分析:刚开始资源全是空的,生产者开始,假设生产者线程正在处理数据,而且时间稍久,
那么后面进入的生产者和消费者都放入了s.queue中,处理结束了以后踢出一个生产者或者
消费者,并且增加一个可消费的资源,假设踢出来的是生产者,那么又进行wait下同样的操作,
假设踢出来的是消费者,消费者对申请的资源进行处理

在系统中:wait(e)申请的空资源数 = 当前生产者 + s.queue中生产者数
         wait(n)申请的实资源数 = 当前消费者 + s.queue中消费者数

e.count = 100;说明当前最多可以有100个生产者同时进入
e.queue 保存的是生产者数
n.count = 100;说明当前最多可以有100个消费者同时进入
n.queue 保存的是消费者数
s.count = 1;说明当前最多可以有1个生产者或者消费者进入临界资源区


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NIO(New I/O)是Java提供的一种基于通道和缓冲区的I/O处理方式,相对于传统的I/O(InputStream/OutputStream)更为高效。 NIO的主要组件包括以下几个部分: 1. 通道(Channel):通道是数据传输的载体,类似于传统的流,但通道可以同时支持读和写操作。通道可以是单向的或双向的,可以与文件或网络套接字关联。 2. 缓冲区(Buffer):缓冲区是一个特定大小的字节数组,用于临时存储数据。通过读写缓冲区,实现数据在通道之间的传输。 3. 选择器(Selector):选择器用于监听多个通道的事件,当一个或多个通道有事件发生时,选择器会将其交给某个线程进行处理。使用选择器可以实现单线程管理多个通道,提高了系统资源利用率。 NIO的工作原理如下: 1. 创建通道:通过打开一个文件或网络套接字,创建相应类型的通道。可以使用FileChannel进行文件读写操作,也可以使用SocketChannel和ServerSocketChannel进行网络通信。 2. 创建缓冲区:根据需要创建合适大小的缓冲区。 3. 数据读取:将数据从通道读取到缓冲区中。 4. 数据处理:对缓冲区中的数据进行处理,例如进行解码、编码、加密等操作。 5. 数据写入:将处理完的数据从缓冲区写入通道,发送给目标。 6. 选择器监听:通过选择器监听通道的事件,例如读就绪、写就绪等。 7. 处理事件:当有事件发生时,选择器会将事件交给对应的线程进行处理。 通过以上步骤,NIO实现了非阻塞的I/O操作,提高了系统的并发能力和响应速度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值