Repository: ethereum/web3.py

Issue:
RuntimeError: release unlocked lock
* Version: 6.8.0
* Python: 3.11.1
* OS: linux
* `pip freeze` output

```
 pip freeze                                                                                       4167ms
aiofiles==23.1.0
aiohttp==3.8.5
aiosignal==1.3.1
alembic==1.11.3
async-timeout==4.0.2
asyncpg==0.28.0
attrs==23.1.0
base58==2.1.1
bitarray==2.7.5
certifi==2023.5.7
charset-normalizer==3.1.0
cytoolz==0.12.1
ecs-logging==2.1.0
eth-abi==4.1.0
eth-account==0.9.0
eth-hash==0.5.2
eth-keyfile==0.6.1
eth-keys==0.4.0
eth-rlp==0.3.0
eth-typing==3.4.0
eth-utils==2.2.0
frozenlist==1.3.3
grpcio==1.57.0
grpcio-tools==1.57.0
hexbytes==0.3.1
html5tagger==1.3.0
httptools==0.5.0
idna==3.4
jsonschema==4.17.3
lru-dict==1.2.0
Mako==1.2.4
MarkupSafe==2.1.2
multidict==6.0.4
numpy==1.25.2
parsimonious==0.9.0
prometheus-client==0.17.1
protobuf==4.23.0
pycryptodome==3.18.0
pydantic==1.10.12
pyrsistent==0.19.3
pyunormalize==15.0.0
PyYAML==6.0
redis==5.0.0
regex==2023.6.3
requests==2.31.0
rlp==3.0.0
sanic==23.6.0
sanic-ext==23.6.0
sanic-routing==23.6.0
SQLAlchemy==2.0.20
toolz==0.12.0
tracerite==1.1.0
typing_extensions==4.5.0
ujson==5.7.0
urllib3==2.0.2
uvloop==0.17.0
web3==6.8.0
websockets==11.0.3
yarl==1.9.2
```


### What was wrong?


* The code which produced the error
```py
    provider = AsyncHTTPProvider(request.app.config.get("ETHEREUM_MAINNET_URL"))
    w3 = AsyncWeb3(provider)

    contract = w3.eth.contract(
        address=MAINNET_TOKEN_ADDRESS_DETECTION,
        abi=single_call_balance_checker_abi,
    )
    address_keys = list(TOKEN_METADATA_MAP.keys())

    (native_balance, balance_values) = await asyncio.gather(
        w3.eth.get_balance(to_checksum_address(address)),
        contract.functions.balances(
            [to_checksum_address(address)],
            address_keys,
        ).call(),
    )
```
* The full output of the error
```py
File "handle_request", line 97, in handle_request
  File "/app/data_service/ethereum/views/balances.py", line 54, in get_balances
    (native_balance, balance_values) = await asyncio.gather(
                                       ^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/eth/async_eth.py", line 435, in get_balance
    return await self._get_balance(account, block_identifier)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/module.py", line 114, in caller
    result = await async_w3.manager.coro_request(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/manager.py", line 264, in coro_request
    response = await self._coro_make_request(method, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/manager.py", line 199, in _coro_make_request
    return await request_func(method, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/gas_price_strategy.py", line 126, in middleware
    return await make_request(method, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/names.py", line 139, in middleware
    return await make_request(method, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/attrdict.py", line 69, in middleware
    response = await make_request(method, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/formatting.py", line 165, in middleware
    response = await make_request(method, params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/buffered_gas_estimate.py", line 58, in middleware
    return await make_request(method, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/middleware/exception_retry_request.py", line 151, in middleware
    return await make_request(method, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/providers/async_rpc.py", line 91, in make_request
    raw_response = await async_make_post_request(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/_utils/request.py", line 239, in async_make_post_request
    response = await async_get_response_from_post_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/_utils/request.py", line 231, in async_get_response_from_post_request
    session = await async_cache_and_return_session(endpoint_uri)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/_utils/request.py", line 141, in async_cache_and_return_session
    async with async_lock(_async_session_pool, _async_session_cache_lock):
  File "/usr/local/lib/python3.11/contextlib.py", line 204, in __aenter__
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/web3/_utils/async_caching.py", line 21, in async_lock
    lock.release()
```
* What type of node you were connecting to.
AsyncHTTPProvider (Infura)


### How can it be fixed?


I tried to reproduce this error locally, but it only occurs in production. 


Discussion:

Resolving patch:
diff --git a/web3/_utils/async_caching.py b/web3/_utils/async_caching.py
--- a/web3/_utils/async_caching.py
+++ b/web3/_utils/async_caching.py
@@ -18,4 +18,5 @@ async def async_lock(
         await loop.run_in_executor(thread_pool, lock.acquire)
         yield
     finally:
-        lock.release()
+        if lock.locked():
+            lock.release()


Test patch: