Python Asyncio: блокировка и условия гонки - PullRequest
0 голосов
/ 03 июня 2018

Я пытаюсь понять библиотеку Python asyncio, и меня несколько удивляет поведение следующего примера:

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)

Если я запускаю вышеупомянутую программу и открываю два запроса к http://0.0.0.0:8080 Iобратите внимание, что для выполнения обоих запросов требуется около трех секунд.Почему это?Разве второй запрос не должен быть заблокирован первым, получившим блокировку?

1 Ответ

0 голосов
/ 03 июня 2018

Я не могу воспроизвести проблему, которую вы описываете.aiohttp не рекомендует использовать глобальные переменные и предлагает использовать объект Application в пользу глобальных переменных.Но они, кажется, не упоминают, что темы вовлечены здесь.Скорее, это скорее общий совет для более чистого кода, чем необходимость - поэтому ваш код должен быть в порядке ...

Я протестировал ваш код с помощью этого примера сценария bash:

#!/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

вывод выглядит примерно так:

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

Возможно, вы захотите убедиться, что фактическое время запуска аналогично.

...