A quoi servent les coroutines et la concurrence en python ?

青灯夜游
Libérer: 2018-09-21 15:19:55
original
2583 Les gens l'ont consulté

Ce chapitre vous présentera le rôle des coroutines et de la concurrence en python, afin que vous puissiez comprendre les avantages et les inconvénients de l'utilisation des coroutines, ainsi que le rôle du framework de concurrence gevent. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

Coroutine

Coroutine est un thread léger en mode utilisateur, également appelé micro-thread.

La coroutine a son propre contexte de registre et sa propre pile. Lorsque le planning est changé, le contexte de registre et la pile sont enregistrés ailleurs. Lors du retour en arrière, le contexte de registre et la pile précédemment enregistrés sont restaurés. Par conséquent : la coroutine peut conserver l'état du dernier appel (c'est-à-dire une combinaison spécifique de tous les états locaux). Chaque fois que le processus rentre, cela équivaut à entrer dans l'état du dernier appel. l'état où il est parti la dernière fois. L'emplacement du flux logique.

Avantages :

  1. Aucune surcharge liée au changement de contexte de thread

  2. Aucune surcharge liée au verrouillage et à la synchronisation des opérations atomiques

  3. Commutez facilement le flux de contrôle et simplifiez le modèle de programmation

  4. Concurrence élevée + évolutivité élevée + faible coût : ce n'est pas un problème pour un processeur de prendre en charge des dizaines de milliers de coroutines. Il est donc très approprié pour le traitement à haute concurrence.

L'opération dite atomique fait référence à une opération qui ne sera pas interrompue par le mécanisme de planification des threads une fois cette opération lancée, elle s'exécutera jusqu'à la fin sans aucun changement de contexte (switch sur un autre fil).

Les opérations atomiques peuvent être une ou plusieurs étapes, mais l'ordre ne peut pas être perturbé ou seule la partie exécutée peut être coupée. Voir dans son ensemble est au cœur de l’atomicité.

Inconvénients :

  1. Impossible d'utiliser des ressources multicœurs : l'essence de la coroutine est un seul thread. Elle ne peut pas utiliser plusieurs cœurs d'un seul processeur en même temps. La coroutine doit être Les processus doivent coopérer pour fonctionner sur plusieurs processeurs. Bien entendu, la plupart des applications que nous écrivons quotidiennement n'ont pas cette nécessité, à moins qu'il ne s'agisse d'applications gourmandes en ressources processeur.

  2. Les opérations de blocage (telles que les IO) bloqueront l'ensemble du programme

Utiliser Gevent

gevent est un framework de concurrence python, avec un micro-thread greenlet comme noyau, utilisant le mécanisme d'écoute des événements epoll et de nombreuses autres optimisations pour le rendre efficace. :

  • Exemple simple

Le sommeil de gevent peut céder le contrôle. Lorsque nous utilisons gevent dans des fonctions restreintes par le réseau ou les E/S, ces fonctions seront planifiées de manière coopérative. déchaîné. Gevent gère tous les détails pour garantir que votre bibliothèque réseau transmettra implicitement les droits d'exécution au contexte greenlet lorsque cela est possible.

import gevent
 
def foo():
    print('running in foo')
    gevent.sleep(0)
    print('com back from bar in to foo')
 
def bar():
    print('running in bar')
    gevent.sleep(0)
    print('com back from foo in to bar')
 
# 创建线程并行执行程序
gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
])
Copier après la connexion

Résultat de l'exécution :

A quoi servent les coroutines et la concurrence en python ?

  • Synchrone et asynchrone

import random
import gevent
 
def task(pid):
    gevent.sleep(random.randint(0, 2) * 0.001)
    print('Task %s done' % pid)
 
def synchronous():
    for i in range(1, 10):
        task(i)
 
def asynchronous():
    threads = [gevent.spawn(task, i) for i in range(10)]
    gevent.joinall(threads)
 
print('Synchronous:')
synchronous()
 
print('Asynchronous:')
asynchronous()
Copier après la connexion

Résultat d'exécution :

A quoi servent les coroutines et la concurrence en python ?

  • Utilisation de coroutine dans une méthode de sous-classe

peut être sous-classée Transform la classe Greenlet et surcharger sa méthode _run, similaire aux modules multi-thread et multi-processus

import gevent
from gevent import Greenlet
 
class Test(Greenlet):
 
    def __init__(self, message, n):
        Greenlet.__init__(self)
        self.message = message
        self.n = n
 
    def _run(self):
        print(self.message, 'start')
        gevent.sleep(self.n)
        print(self.message, 'end')
 
tests = [
    Test("hello", 3),
    Test("world", 2),
]
 
for test in tests:
    test.start()  # 启动
 
for test in tests:
    test.join()  # 等待执行结束
Copier après la connexion
  • Utiliser Monkey Patch pour modifier la bibliothèque standard du système (changer automatiquement de coroutines)

Lorsqu'un greenlet rencontre une opération IO, telle que l'accès au réseau, il basculera automatiquement vers d'autres greenlets, attendra que l'opération IO soit terminée, puis reviendra pour continuer l'exécution au moment approprié. temps.

Étant donné que les opérations d'E/S prennent beaucoup de temps, le programme est souvent laissé dans un état d'attente. Avec gevent changeant automatiquement de coroutines pour nous, il est garanti que les greenlets sont toujours en cours d'exécution au lieu d'attendre les IO.

Étant donné que la commutation est automatiquement effectuée lors des opérations d'E/S, gevent doit modifier certaines des bibliothèques standard fournies avec Python. Ce processus est effectué via Monkey Patch au démarrage

import gevent
import requests
from gevent import monkey
 
monkey.patch_socket()
 
def task(url):
    r = requests.get(url)
    print('%s bytes received from %s' % (len(r.text), url))
 
gevent.joinall([
    gevent.spawn(task, 'https://www.baidu.com/'),
    gevent.spawn(task, 'https://www.qq.com/'),
    gevent.spawn(task, 'https://www.jd.com/'),
])
Copier après la connexion

Sortie d'exécution :

A quoi servent les coroutines et la concurrence en python ?

On peut voir que les trois opérations réseau sont exécutées simultanément et que l'ordre de fin est différent

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal