您的位置:首页 > 其它

操作系统学习笔记——生产者与消费者,读者和写者

2012-04-29 15:13 316 查看
i. 生产者生产一条数据

1. 首先查看缓冲区能否放入数据,有没有空的位置,如果有往下执行,否则说明缓冲区全

满了,消费者可能干什么去了没有来取数据,所以生产者阻塞等待资源,当一定的时候被唤醒(有空的了)。在此处,生产者如果发现缓冲区已经满了,生产者阻塞在此处。

2. 之后查看临界区是否可用(有没有进程在临界区),否则必须等待使用权,当使用临界资源的进程退出唤醒之。假设3个生产者都已经申请到资源,但是到此处时,只能有一个生产者可以进入,所以又要被阻塞一次。

3. 存入一条数据

4. 退出临界区,归还使用权

5. 数据单元+1,唤醒消费者。

ii. 消费者消费一条数据

1. 首先查看有数据单元,如果有执行,否则消费者阻塞等待资源,直到被生产者唤醒(信号?)

2. 查看临界区是否可用,如果可用执行,否则阻塞等待使用权。

3. 从缓冲区取一条数据。

4. 归还临界区使用权

5. 空单元+1,唤醒一个生产者(数据单元-1,生产者可以生产了)

6. 消费数据

const int buffersize = 10; //缓冲区大小

semaphore s = 1; //互斥信号量,初始化为1

semaphore n = 0; //资源信号量,数据单元,初始化为0

semaphore e = buffersize //资源信号量,空存储单元

void producer()

{

while(true)

{

produce(); //生产一条数据

wait(e); //i.1,查看缓冲层是否可用

wait(s); //i.2,查看临界区是否可用

dosomething() //i.3,存入一条数据

signal(s); //i.4,退出缓冲区,归还使用权。

signal(n); //i.5,数据单位+1,唤醒消费者

}

}

void consumer()

{

while(true)

{

wait(n); //ii.1查看缓冲区是否可用

wait(s); //ii.2查看临界区是否可用

dosomething(); //ii.3取一条数据

signal(s); //ii.4归还临界区使用权

signal(e); //ii.5空单元+1,唤醒生产者

consume(); //消费数据

}

}

七 读者写者问题

1. 问题描述及满足的条件

l 该问题为多个进程访问一个共享数据区建立的一个通用模型,其中若干读进程只能读数据,若干写进程只能写数据。

l 允许多个读者进程可以同时读数据。

l 不允许多个写者同时写数据,只能互斥写数据。

l 若有写者进程正在写数据,则不允许读者进程读数据。

2. 如何控制读者和写者问题

l 如果采用生产者/消费者问题解决方法,严格互斥任何读者和写者进程,可以保证数据更新操作的正确性。

l 但是对于若干读进程,严格互斥,将影响效率,应该让读者同时读数据。

l 如果一个写者进程正在修改数据,别的写者及任何读者都不难访问该数据。

3. 读者优先

l 当一个读者正在读数据,允许其他读者进入。

l 现在假设一个写者到来,由于写操作是排他的,需要阻塞等待,如果一直都有新的读者陆续到来,写者的写操作将被严重推迟。

这种方法称为“读者优先”,一旦读者正在读数据,允许多个读者同时进入读数据,只

有当全部读者退出,才允许写者进入写数据,对写者不公平.

int readcount = 0; //读者个数

semaphore wsem = 1; //互斥信号量,初始化为1,互斥读者和写者

semaphore x = 1; //互斥修改readcount变量

void read()

{

while(true)

{

///x:读者互斥修改readcount这个变量

wait(x);

if(++readcount == 1)

wait(wsem);

signal(x);

///

readData(); //读数据

wait(x);

if(--readcount == 0)

signal(wsem);

signal(x);

}

}

void write()

{

while(true)

{

wait(wsem);

writeData();

signal(s);

}

}

4. 写者优先

l 为了防止“读者优先”可能导致写者饥饿,可以考虑写者优先。

l 即,当共享数据区被读者占用,后续紧邻到达的读者可以继续进入,若这时有一个写者到来且阻塞等待,则写者后面到来的若干读者全部阻塞。

l 这种方案解决写者饥饿问题,但降低了并发程度使系统性能较差。

int readcount = 0; //读者个数

int writecount = 0; //写者个数

semaphore wsem = 1; //写者信号量,互斥写者

semaphore rsem = 1; //读者信号量,互斥读者

semaphore x = 1; //互斥修改readcount变量

semaphore y = 1; //互斥修改writecount变量

semaphore z = 1; //

void read()

{

while(true)

{

wait(z); //不让读者排成长队

wait(rsem);

wait(x);

if(++readcount == 1)

wait(wsem);

signal(x);

signal(rsem);

signal(z);

///

readData(); //读数据

wait(x);

if(--readcount == 0)

signal(wsem);

signal(x);

}

}

void write()

{

while(true)

{

wait(y); //互斥

if(++writecount == 1)

wait(rsem); //阻塞读者

signal(y);

wait(wsem); //写者写数据

writeData();

signal(wsem);

wait(y);

if(--writecount == 0)

signal(rsem);

signal(y);

signal(s);

}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: