[Async-sig] "read-write" synchronization
Chris Jerdonek
chris.jerdonek at gmail.com
Sun Jun 25 23:34:50 EDT 2017
So here's one approach I'm thinking about for implementing
readers-writer synchronization. Does this seem reasonable as a
starting point, or am I missing something much simpler?
I know there are various things you can prioritize for (readers vs.
writers, etc), but I'm less concerned about those for now.
The global state is--
* reader_count: an integer count of the active (reading) readers
* writer_lock: an asyncio Lock object
* no_readers_event: an asyncio Event object signaling no active readers
* no_writer_event: an asyncio Event object signaling no active writer
Untested pseudo-code for a writer--
async with writer_lock:
no_writer_event.clear()
# Wait for the readers to finish.
await no_readers_event.wait()
# Do the write.
await write()
# Awaken waiting readers.
no_writer_event.set()
Untested pseudo-code for a reader--
while True:
await no_writer_event.wait()
# Check the writer_lock again in case a new writer has
# started writing.
if not writer_lock.locked():
# Then we can do the read.
break
reader_count += 1
if reader_count == 1:
no_readers_event.clear()
# Do the read.
await read()
reader_count -= 1
if reader_count == 0:
# Awaken any waiting writer.
no_readers_event.set()
One thing I'm not clear about is when the writer_lock is released and
the no_writer_event set, are there any guarantees about what coroutine
will be awakened first -- a writer waiting on the lock or the readers
waiting on the no_writer_event?
Similarly, is there a way to avoid having to have readers check the
writer_lock again when a reader waiting on no_writer_event is
awakened?
--Chris
On Sun, Jun 25, 2017 at 3:27 PM, Chris Jerdonek
<chris.jerdonek at gmail.com> wrote:
> On Sun, Jun 25, 2017 at 3:09 PM, Nathaniel Smith <njs at pobox.com> wrote:
>> On Sun, Jun 25, 2017 at 2:13 PM, Chris Jerdonek
>> <chris.jerdonek at gmail.com> wrote:
>>> I'm using asyncio, and the synchronization primitives that asyncio
>>> exposes are relatively simple [1]. Have options for async read-write
>>> synchronization already been discussed in any detail?
>>
>> As a general comment: I used to think rwlocks were a simple extension
>> to regular locks, but it turns out there's actually this huge increase
>> in design complexity. Do you want your lock to be read-biased,
>> write-biased, task-fair, phase-fair? Can you acquire a write lock if
>> you already hold one (i.e., are write locks reentrant)? What about
>> acquiring a read lock if you already hold the write lock? Can you
>> atomically upgrade/downgrade a lock? This makes it much harder to come
>> up with a one-size-fits-all design suitable for adding to something
>> like the python stdlib.
>
> I agree. And my point about asyncio's primitives wasn't a criticism or
> request that more be added. I was asking more if there has been any
> discussion of general approaches and patterns that take advantage of
> the event loop's single thread, etc.
>
> Maybe what I'll do is briefly write up the approach I have in mind,
> and people can let me know if I'm on the right track. :)
>
> --Chris
More information about the Async-sig
mailing list