Я оказался в ситуации, когда мне нужно синхронизировать задачи Trio с потоками Python. На данный момент я использую threading.Lock
объекты, которые Trio задачи должны приобретать с trio.run_sync_in_worker_thread(lock.acquire)
.
Я думаю, что также можно использовать trio. Lock
trio. Lock
блокировки и получайте их с помощью trio.BlockingTrioPortal.run_sync(lock.acquire)
.
Имеет ли одно из этих решений преимущество над другим?
Можно ли в принципе сделать лучше, чем это? Например, для реализации "родного" метода трио, который ждет threading.Lock
без необходимости отдельного рабочего потока или есть фундаментальные причины, почему это требуется?
Оба метода в порядке. Я бы рекомендовал использовать метод, который вызывает меньше работы, т.е. Если внешний поток получает блокировку по десять раз за одно задание Trio, затем используйте блокировку потока и наоборот.
threading.Lock
всегда блокирует поток, пытаясь его приобрести, поэтому для его получения из Trio требуется отдельный поток (который ваш первый метод уже делает в любом случае), или владелец блокировки должен сигнализировать о задаче Trio о том, что он освободил блокировку ( который ваш второй метод делает в любом случае), поэтому нет явного преимущества для реализации решения более низкого уровня.
Маттиас отвечает отлично. Чтобы добавить: есть одно теоретическое преимущество использования trio.Lock
, то есть, то, по крайней мере, вызовы Trio-side будут поддерживать отмену. Однако в настоящее время существует и основное практическое препятствие, которое заключается в том, что в настоящее время, используя BlockingTrioPortal
для вызова lock.acquire
и lock.release
, не работает :-(. См. Эту проблему, которую я только что написал для получения подробностей. 'll придется использовать threading.Lock
и run_sync_in_worker_thread
его исправления, я бы по умолчанию использовал trio.Lock
для аннулирования.
EDIT: при дальнейшей мысли я вспомнил, что у трио уже есть версия Lock
которая работает с BlockingTrioPortal
, она просто trio.Semaphore(1, max_value=1)
: trio.Semaphore(1, max_value=1)
. Мы все равно должны исправить общий случай, но в то же время это может быть полезной вещью.
trio.BlockingTrioPortal.run(lock.acquire)
посколькуtrio.Lock.acquire
является асинхронным методом.