简体   繁体   中英

Python asyncio: blocking and race conditions

I'm trying to understand python's asyncio library, and am somewhat surprised by the behavior of the following example:

import asyncio
import time

from aiohttp import web


_lock_table = {'locked': False}


async def process(text):
    # wait while we're blocked
    while _lock_table['locked']:
        await asyncio.sleep(1)

    _lock_table['locked'] = True

    # hold the lock for three seconds
    # simulates "processing something"
    await asyncio.sleep(3)

    # release the lock
    _lock_table['locked'] = False


async def request_handler(request):
    text = request.query.get('text')

    start_time = time.time()
    await process(text)
    end_time = time.time()

    return web.Response(
        body='text: {}, request time: {}'.format(text, end_time - start_time),
        content_type='text/html'
    )


app = web.Application()
app.router.add_route('GET', '/', request_handler)

web.run_app(app)

If I start the above program and open up two requests to http://0.0.0.0:8080 I see that both requests take around three seconds to complete. Why is this? Shouldn't the second request be blocked by the first one that acquires the lock?

I can't reproduce the problem you are describing. aiohttp discourages the use of global variables and suggests to use the Application object in favor of globals. But they don't seem to mention that threads are involved here. It rather seems to be a general hint for cleaner code than a necessity - so your code should be fine...

I tested your code with this example bash script:

#!/bin/bash

pids=()
range=$(seq 1 10)
url='http://127.0.0.1:8080/?text='
for i in $range; do
    curl -o $i.txt "${url}$(date +%H%M%S)" 2>/dev/null &
    pids[$i]=$!
done

wait ${pids[$@]}

for i in $range; do
    echo "$i $(cat $i.txt)"
done

the output looks something like this:

1 text: 222331, request time: 24.153167724609375
2 text: 222331, request time: 15.077209711074829
3 text: 222331, request time: 27.17816162109375
4 text: 222331, request time: 6.0150146484375
5 text: 222331, request time: 18.09979248046875
6 text: 222331, request time: 21.1268310546875
7 text: 222331, request time: 3.004944086074829
8 text: 222331, request time: 9.03411865234375
9 text: 222331, request time: 12.050049066543579
10 text: 222331, request time: 30.205841302871704

You might want to make sure that the actual start time is similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM