wrapt 2.2.0 adds proper async support to the synchronized decorator and context manager. Previously, applying @wrapt.synchronized to async def functions appeared to work but didn't actually serialize execution — the threading.RLock was acquired and released around coroutine construction, not around the awaited body. Now the decorator detects coroutine functions and uses asyncio.Lock instead, with lock acquisition happening inside the coroutine. The async with form of the context manager is also supported. One key difference: unlike the synchronous path which uses threading.RLock (reentrant), the async path uses asyncio.Lock (non-reentrant), meaning nested synchronized async calls on the same instance will deadlock. This is intentional — asyncio has no standard RLock equivalent. The recommended workaround is delegating to private unsynchronized helpers from public synchronized methods.
Table of contents
A quick recap of synchronizedWhere it fell apart on asyncWhat 2.2.0 changesThe reentrancy differenceWrapping upSort: