The problem: You want to have a critical section of code where concurrent read operations are permitted but exclusive access for write operations — multiple readers may read data in parallel but only a single writer is allowed to write data at any one time.
Here's an implementation using the eventlet library:
from eventlet import greenthread, hubs class ReadWriteLock(object): """ Usage:: lock = ReadWriteLock() with lock.reader(): do_read_ops() with lock.writer(): do_write_ops() """ def __init__(self): self.counter = 0 self._read_waiters = set() self._write_waiters = set() def reader(self): return self.Reader(self) def writer(self): return self.Writer(self) class Base(object): def __init__(self, parent): self.parent = parent def _acquire(self, waiters): waiters.add(greenthread.getcurrent()) try: while self.parent.counter != 0: hubs.get_hub().switch() finally: waiters.discard(greenthread.getcurrent()) def _exit(self): for waiters, fn in ( (self.parent._read_waiters, lambda x: x >= 0), (self.parent._write_waiters, lambda x: x == 0), ): if not waiters: continue hubs.get_hub().schedule_call_global( 0, self._release, waiters, fn, ) def _release(self, waiters, fn): if waiters and fn(self.parent.counter): waiters.pop().switch() class Reader(Base): def __enter__(self): if self.parent.counter < 0: self._acquire(self.parent._read_waiters) self.parent.counter += 1 def __exit__(self, *args, **kwargs): self.parent.counter -= 1 self._exit() class Writer(Base): def __enter__(self): if self.parent.counter != 0: self._acquire(self.parent._write_waiters) self.parent.counter -= 1 def __exit__(self, *args, **kwargs): self.parent.counter += 1 self._exit()