1

I find myself in the situation that I need to synchronize Trio tasks with Python threads. At the moment, I am using threading.Lock objects that Trio tasks have to acquire with trio.run_sync_in_worker_thread(lock.acquire).

I think it should also be possible to use trio. Lock locks and have the threads acquire them with trio.BlockingTrioPortal.run_sync(lock.acquire).

Does either of these solutions have advantages over the other?

Would in in principle be possible to do better than this? E.g. to implement a "native" trio method that waits for a threading.Lock without the need for a separate worker thread, or are there fundamental reasons why this is required?

Nikratio
  • 2,138
  • 2
  • 25
  • 40

2 Answers2

1

Both methods are fine. I'd recommend to use the method which causes less work, i.e. if the external thread acquires the lock ten times per Trio task's once, then use a thread lock, and vice versa.

A threading.Lock always blocks the thread trying to acquire it, so taking it from Trio either requires a separate thread (which your first method already does anyway), or the lock's holder needs to signal the Trio task that it has released the lock (which your second method does anyway), so there is no clear advantage for implementing a lower-level solution.

Matthias Urlichs
  • 1,789
  • 14
  • 26
1

Matthias's answer is excellent. To add: there is one theoretical advantage to using a trio.Lock, which is that then at least the Trio-side calls will support cancellation. However, there is currently also a major practical obstacle, which is that currently, using BlockingTrioPortal to call lock.acquire and lock.release doesn't work :-(. See this issue I just filed for details. So until that's fixed, you'll have to use threading.Lock and run_sync_in_worker_thread. After it's fixed, though, I would default to using trio.Lock for the cancellation thing.

EDIT: on further thought, I remembered that trio does already have a version of Lock that works with BlockingTrioPortal, it's just obscure: trio.Semaphore(1, max_value=1). We should still fix the general case, but in the mean time this might be a useful thing to know about.

Nathaniel J. Smith
  • 9,038
  • 4
  • 35
  • 46