Does Pythons asyncio lock.acquire maintain order?

2024/11/17 13:32:43

If I have two functions doing

async with mylock.acquire():....

Once the lock is released, is it guaranteed that the first to await will win, or is the order selected differently? (e.g. randomly, arbitrarily, latest, etc.)

The reason I'm asking, if it is not first-come-first-served, there might easily be a case of starvation where the first function attempting to acquire the lock never gets wins it.

Answer

When we talk about how something works it's important to distinguish guarantee expressed in specification and side-effect of implementation. First one shouldn't be changed (at least, within major version), second one can be changed any time in the future.

Martijn's answer clearly shows that current implementation preserves order. What about guarantee for future?

Official documentation for Python 3.6 provides guarantee:

only one coroutine proceeds when a release() call resets the state to unlocked; first coroutine which is blocked in acquire() is being processed.

Interesting thing is that neither documentation for Python 3.7 nor documentation for Python 3.8 dev have this line, not sure if it's intentional though. However class's docstring on github has guarantee.

It's also worth mentioning that threading.Lock (prototype for asyncio's lock) explicitly says that order is undefined:

only one thread proceeds when a release() call resets the state to unlocked; which one of the waiting threads proceeds is not defined, and may vary across implementations.


Long story short, right now only class's docstring promises to maintain order. It's also fair to note that implementation of lock is unlikely to being changed in the nearest future.

Yet imagine however someone will change it (to increase performance, for example). Will docstring be enough to prevent from implementing lock with undefined order? It's up to you to decide.

If your code critically depends on preserving order and expected to have long life cycle nothing bad if you create your own lock (sub)class which will explicitly guarantee order (OrderedLock or something). You may just vendorize current implementation.

If situation is simpler you may choose not to bother with it and use current implementation.

https://en.xdnf.cn/q/71208.html

Related Q&A

Howto ignore specific undefined variables in Pydev Eclipse

Im writing a crossplatform python script on windows using Eclipse with the Pydev plugin. The script makes use of the os.symlink() and os.readlink() methods if the current platform isnt NT. Since the os…

Faster way to calculate hexagon grid coordinates

Im using the following procedure to calculate hexagonal polygon coordinates of a given radius for a square grid of a given extent (lower left upper right):def calc_polygons(startx, starty, endx, endy,…

Why is -0.0 not the same as 0.0?

I could be missing something fundamental, but consider this interpreter session1:>>> -0.0 is 0.0 False >>> 0.0 is 0.0 True >>> -0.0 # The sign is even retained in the output…

scrapy: exceptions.AttributeError: unicode object has no attribute dont_filter

In scrapy, I am getting the error exceptions.AttributeError: unicode object has no attribute dont_filter. After searching around, I found this answer (which made sense as it was the only bit of code I …

Django Class Based View: Validate object in dispatch

Is there a established way that i validate an object in the dispatch without making an extra database call when self.get_object() is called later in get/post?Here is what i have so far (slightly alter…

Python very slow as compared to Java for this algorithm

Im studying algorithms and decided to port the Java Programs from the textbook to Python, since I dislike the Java overhead, especially for small programs, and as an exercise.The algorithm itself is ve…

fd.seek() IOError: [Errno 22] Invalid argument

My Python Interpreter (v2.6.5) raises the above error in the following codepart:fd = open("some_filename", "r") fd.seek(-2, os.SEEK_END) #same happens if you exchange the second arg…

When is a variable considered constant in terms of PEP8 naming styles?

In keeping with PEP8 conventions, in a .py I can define constants as:NAME = "Me" AGE = "Old" GENER = "Male"If a .txt contained Me Old Male on a single line, and in anothe…

Average Date Array Calculation

I would like to get the mean of the following dates. I thought about converting all the data to seconds and then averaging them. But there is probably a better way to do it.date = [2016-02-23 09:36:26,…

DRF: Serializer Group By Model Field

I want my api to return Account objects grouped by the account_type field in the model. I want to do this so that the grouped accounts are easier to access in my JS code. This is what is returned now:[…