Ви вже отримали досить різноманітні відповіді, починаючи від "фальшивих ниток" і закінчуючи зовнішніми фреймворками, але я бачив, що ніхто не згадував Queue.Queue
- "таємний соус" потокової роботи CPython.
Щоб розширити: поки вам не потрібно перекривати обробку процесором із чистим Python (у цьому випадку вам це потрібно, multiprocessing
але він також постачається із власною Queue
реалізацією, тому ви можете з певними обережностями застосувати загальну пораду I Даю ;-), вбудований Python threading
буде робити ... але він зробить це набагато краще, якщо ви використовуєте його з розумом , наприклад, наступним чином.
«Забудьте» про спільну пам’ять, нібито головний плюс потокової роботи проти багатопроцесорної обробки - вона не працює добре, вона погано масштабується, ніколи не була, ніколи не буде. Використовуйте спільну пам’ять лише для структур даних, які налаштовані один раз перед тим, як ви породите підпотоки і ніколи не змінювались згодом - для всього іншого зробіть єдиний потік, відповідальний за цей ресурс, і спілкуйтеся з цим потоком через Queue
.
Присвятіть спеціалізований потік кожному ресурсу, який ви зазвичай думаєте захищати замками: змінною структурою даних або цілісною їх групою, підключенням до зовнішнього процесу (БД, серверу XMLRPC тощо), зовнішньому файлу тощо тощо. Отримайте невеликий пул потоків для загальних завдань, у яких немає або потрібен спеціальний ресурс такого роду - не породжуйте потоки, коли і коли це потрібно, інакше накладні витрати на переключення потоків вас захоплять.
Зв'язок між двома потоками завжди здійснюється через Queue.Queue
- форму передачі повідомлень, єдину розумну основу для багатопроцесорної обробки (крім транзакційної пам'яті, яка є перспективною, але для якої я не знаю жодної реалізації, гідної реалізації, крім In Haskell).
Кожен виділений потік, що управляє одним ресурсом (або невеликим згуртованим набором ресурсів), прослуховує запити в конкретному екземплярі Queue.Queue. Потоки в пулі чекають на одній спільній Queue.Queue (Черга надійно захищена від потоків і не підведе вас у цьому).
Потоки, яким просто потрібно поставити в чергу запит на якусь чергу (спільну чи виділену), роблять це, не чекаючи результатів, і рухаються далі. Потоки, які врешті-решт потребують результату або підтвердження для черги запиту пару (запит, черга отримання) з екземпляром Queue.Queue, яку вони щойно зробили, і врешті-решт, коли відповідь або підтвердження є необхідними для продовження, вони отримують (очікування ) з черги отримання. Будьте впевнені, що готові отримувати відповіді на помилки, а також реальні відповіді чи підтвердження (Twisted's deferred
чудово підходять для організації такого роду структурованих відповідей, BTW!).
Ви також можете використовувати Чергу, щоб "припаркувати" екземпляри ресурсів, які можуть бути використані будь-яким одним потоком, але ніколи не будуть спільно використовуватися між кількома потоками одночасно (з'єднання БД з деякими компонентами DBAPI, курсори з іншими тощо) - це дозволяє Вам розслабитися вимога виділеного потоку на користь більшого об’єднання (потік пулу, який отримує із загальної черги запит, що потребує ресурсу, що стоїть у черзі, отримає цей ресурс із відповідної черги додатків, чекаючи, якщо потрібно, тощо, тощо).
Twisted - це насправді хороший спосіб організувати цей менует (або квадратний танець, залежно від ситуації), не лише завдяки відкладеним, але завдяки його звуковій, міцній, масштабованій базовій архітектурі: ви можете організувати речі, щоб використовувати потоки або підпроцеси, лише коли справді виправдано, роблячи більшість речей, які зазвичай вважаються гідними потоків, в одній потоковій події.
Але я усвідомлюю, що Twisted не для всіх - підхід "виділити або об’єднати ресурси, використовувати Чергу до wazoo, ніколи не робити нічого, що потребує блокування, або, забороняйте Гвідо, будь-яку ще більш просунуту процедуру синхронізації, таку як семафор або умова". як і раніше використовувати, навіть якщо ви просто не можете обернути голову асинхронними керованими подіями методологіями, і все одно забезпечите більше надійності та продуктивності, ніж будь-який інший широко застосовний підхід до різьблення, який я коли-небудь стикався.