Is Lock protection needed in synchronous functions when using asyncio framework?

69 Views Asked by At

My question in a nutshell is, how exactly does the asyncio framework executes code? Let's say I have some synchronous function which uses some data e.g. in a global variable. This context is fully synchronous, there are no IO-operations. This function will be called by some other functions which are in general asynchronous. My question now is: Do I need to use a Lock in the synchronous function (then I would have to make it async) to protect the "shared" data of e.g. the global variable?

If I understood it correctly the asyncio framework executes async code until it has to "await" something. But this would mean that this synchronous context will always be executed as a whole and therefore wouldn't need protection by an asyncio.Lock, right?

Example:

SHARED_MAP: dict[str, int] = {}

def get_entry(key: str) -> int:
    # Do I need to use a Mutex-Lock here?
    if key not in SHARED_MAP:
        SHARED_MAP[key] = randint(1, 10)

    return SHARED_MAP[key]

async def foo():
    # ...
    entry1 = get_entry("foo")
    await asyncio.sleep(0.1)
    entry2 = get_entry("bar")
    await asyncio.sleep(0.1)
    # ...

asyncio.run(foo())

I fooled around a bit with asyncio.sleeps and costly arraycopy operations but the code did not break. So either I'm not good enough to break my code or asyncio indeed exectutes until the next await statement.

PS: If my guess is correct and asyncio executes until the next await statement, can one say in general that if the Awaitable is a Coroutine that this will be executed immediately? Such that the only blocking things are Future objects?

0

There are 0 best solutions below