读者写者问题----公平策略(python测试)

读者写者问题----公平策略(python测试)

问题描述

一个数据对象若被多个并发进程所共享,且其中一些进程只要求读该数据对象的内容,而另一些
进程则要求写操作,对此,把只想读的进程称为“读者”,而把要求写的进程称为“写者”。在
读者–写着问题中,任何时刻要求“写者”最多只允许有一个,而读者则允许有多个。因为多个
读者的行为互不干扰,他们只是读数据,而不改变数据对象的内容,而写者则不同,他们要改变数据对象的内容,如果他们同时操作,则数据对象的内容将会改变的不可知。

限制条件

  • 允许任意多的读进程同时读;
  • 一次只允许一个写进程写操作;
  • 如果有一个写进程正在进行写操作,禁止任何读进程进行读操作。

利用公平策略

让读者与写者之间的执行有着较好的优先权,给出下面两条公平策略
① 规则1:在一个读序列中,如果有写者在等待,那么就不允许有新的读者开始执行。
② 规则2:在一个写操作结束时,所有等待的读者应该比下一个写者有更高的优先权。
为了解决“写着与写着”和“写着与第一个读者”的互斥问题即可,为此引入互斥信号量file。
为了记录谁是第一个读者,可以用一个全局整型变量Rcount做一个计数器。
全局变量Rcount,该变量又是一个临界资源,引入信号量read
在读者优先的算法中,当读者进行时,如有写着在等待的情况下,新的读者仍然会被进行,直到所有读操作完成之后,等待写者才可能被进行,对于读操作频繁的系统而言,很容易使得写者处于较长的等待时间,以至于使得写进程处于“饿死”的现象中,让读者与写者较为公平的进行,提出上面的公平策略,对于读-写-读这样的进程,当第一个读者进行时,第二个处于等待中,第二个读进程不能被执行,当运行第二个读进程时,应被放入到阻塞队列中,
引入一个信号量flag,初始值为1,当写进程触发时,P(flag),当新的读者来到时同样执行P(flag),此时由于写进程进行了P操作,该新的读进程就无法继续运行,而被放入到阻塞队列中,直到写进程执行完放出V操作,新的读者才可能被执行
对于写-读-写这样执行序列,分析同上。

伪代码

semaphore read = 1;   //对Rcount临界资源访问的信号量
semaphore flag = 1; //执行公平策略相关的信号量
semaphore file = 1;   //解决“写着与写着”和“写着与第一个读者”
int Rcount = 0; //记录正在进行的读者数量

void reader()
{
    while (true)
    {
        prepare to read...//准备执行读操作之前相关的操作
        P(flag);//首先要检查是否写进程等待,或者给后面的写进程表示已经有读进程等待中
        P(read);//对临界资源Rcount进行互斥访问
        if (Rcount == 0)
            P(file);//有读者进行读操作,写进程不能执行
        Rcount++;
        V(read);
        V(flag);
        ....
        reading//执行读操作
        ....
        P(read);//对临界资源Rcount进行互斥访问
        Rcount--;
        if (Rcount == 0)
            V(file);
        V(read);
        ...//读操作之后的事务
    }
}

void writer()
{
    while (true)
    {
        prepare to write... //准备执行写操作之前相关的操作
        P(flag);//首先要检查是否读进程等待,或者给后面的读进程表示已经有写进程等待中
        P(file);//读者,写着不能再访问
        .....
        writing//执行写操作
        .....
        V(file);
        V(flag);
        ...//写操作后续操作
    }
}

测试

import time
import threading
from threading import Semaphore
import random


Rcount = 0  # 进行的读者队列数量
Flag = Semaphore(1)  # 解决公平策略添加的
Rmutex = Semaphore(1)  # 对临界资源Rcount的互斥访问
File = Semaphore(1)  # 解决“写着与写着”和“写着与第一个读者”的互斥问题


def reader(i):
    print('reader'+str(i)+' waiting to read\n', end='')
    Flag.acquire()
    Rmutex.acquire()
    global Rcount
    if Rcount == 0:
        File.acquire()
    Rcount += 1
    Rmutex.release()
    Flag.release()
    print('reader'+str(i)+' reading\n', end='')
    time.sleep(random.randint(1, 5))
    print('reader'+str(i)+' finish read\n', end='')
    Rmutex.acquire()
    Rcount -= 1
    if Rcount == 0:
        File.release()
    Rmutex.release()


def writer(i):
    print('writer'+str(i)+' waiting to write\n', end='')
    Flag.acquire()
    File.acquire()
    print('writer'+str(i)+' writing\n', end='')
    time.sleep(random.randint(1, 5))
    print('writer'+str(i)+' finish write\n', end='')
    File.release()
    Flag.release()


if __name__ == '__main__':
    times = 10
    rwlist = []
    for _ in range(times):
        rwlist.append(random.randint(0, 1))
    print(rwlist)
    print('其中1表示读者进程,0表示写者进程')
    rindex = 1
    windex = 1
    for i in rwlist:
        if i == 1:
            t = threading.Thread(target=reader, args=(rindex, ))
            rindex += 1
            t.start()
        else:
            t = threading.Thread(target=writer, args=(windex, ))
            windex += 1
            t.start()

输出

[0, 1, 1, 1, 1, 1, 0, 1, 0, 0]
其中1表示读者进程,0表示写者进程
writer1 waiting to write
writer1 writing
reader1 waiting to read
reader2 waiting to read
reader3 waiting to read
reader4 waiting to read
reader5 waiting to read
writer2 waiting to write
reader6 waiting to read
writer3 waiting to write
writer4 waiting to write
writer1 finish write
reader1 reading
reader2 reading
reader3 reading
reader4 reading
reader5 reading
reader2 finish read
reader4 finish read
reader1 finish read
reader3 finish read
reader5 finish read
writer2 writing
writer2 finish write
reader6 reading
reader6 finish read
writer3 writing
writer3 finish write
writer4 writing
writer4 finish write

Process finished with exit code 0

总结

从上面的结果可以较好的观察出读者执行中有写者在等待时,不会有新的读者去执行读操作,同时写者执行有读者在等待的情况下同样不会有新的写者去执行。
该算法并不能严格的去按照给定读者与写者的顺序去执行。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值