Reader Writer Problem
void read()
{
while(true):
{
P(r);
rc++;
if(rc == 1)
P(w);
V(r);
// read
P(r);
rc--;
if(rc == 0)
V(w);
V(r);
}
}
This piece of code use simpy to implement reader writer problem. And besides, it can avoid writer starvation problem:
It set up and maximum reading time.
When it detects there is too many readers reading, new coming reader thread has to wait certain amount of time to allow the writer be able to access the shared resource.
code
import simpy
import random
rc = 0
req = None
max_operation_time = 5
class reader_manager(object):
def __init__(self, env, lock):
self.env = env
self.task_list = []
self.action = env.process(self.run())
self.est_time = env.now
self.lock = lock
def addTask(self, reader_index, reading_time):
self.task_list.append((reader_index, reading_time))
def run(self):
global rc
while True:
yield self.env.timeout(0.2)
#if len(self.task_list) > 4:
if rc > 3:
print('too many tasks (%s)' % rc)
#print('too many tasks (%s)' % len(self.task_list))
yield env.timeout(max_operation_time * 2 + 1)
if not self.task_list:
continue
reader_idx = self.task_list[0][0]
reading_time = self.task_list[0][1]
self.task_list.pop(0)
#print('%s %s %s' % (env.now, reader_idx, reading_time))
self.env.process(reader(self.env, self.lock, reader_idx, reading_time))
def reader(env, lock,reader_index, reading_time):
global rc
global req
rc = rc+1
if rc == 1:
req = lock.request()
yield req
print("%s reader is reading at %s" %(reader_index,env.now))
yield env.timeout(reading_time)
print("%s reader has finished reading at %s" %(reader_index,env.now))
rc = rc-1
if rc == 0:
lock.release(req)
yield env.timeout(0.1)
def writer(env, lock):
while True:
yield env.timeout(random.randint(0, 5))
with lock.request() as req:
yield req
print("I am writing! at %s" %env.now)
yield env.timeout(random.randint(0, 10))
print("I have finished writing at %s" %env.now)
def task_gen(env, rm):
idx = 0
while True:
#t = random.randint(0, 2)
yield env.timeout(2)
#print('%s' % t)
#rm.addTask(random.randint(0, 10), random.randint(0, 10))
rm.addTask(idx, random.randint(0, 10))
idx = idx + 1
env = simpy.Environment()
lock = simpy.Resource(env, capacity=1)
#lockcount = simpy.Resource(env, capacity=1)
rm = reader_manager(env, lock)
env.process(task_gen(env, rm))
env.process(writer(env, lock))
#rm.addTask(1, 15)
#rm.addTask(2, 15)
#rm.addTask(3, 15)
#rm.addTask(4, 15)
env.run(until=200)
#env.process(reader(env, lock, 1, random.random()))
#env.process(reader(env, lock, 2, random.random()))
#env.process(reader(env, lock, 3, random.random()))
#env.process(reader(env, lock, 4, random.random()))
#env.process(writer(env, lock,2))
#env.run(until=15)