English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In letzter Zeit habe ich über die Python-Koncurrency gelernt und habe eine Zusammenfassung über Mehrprozess, Multithreading, Asynchronität und Koroutines gemacht.
I. Multithreading
Multithreading ermöglicht es, dass mehrere Kontrollrechte in einem Prozess existieren, um sicherzustellen, dass mehrere Funktionen gleichzeitig aktiv sind und ihre Operationen gleichzeitig ausgeführt werden können. Sogar ein Single-CPU-Rechner kann durch ständiges Umschalten zwischen den Befehlen verschiedener Threads den Eindruck erwecken, dass Multithreading gleichzeitig ausgeführt wird.
Multithreading entspricht einem Synchronisationsystem. Ein Synchronisationsystem führt in der Regel mehrere Aufgaben gleichzeitig aus. Wenn mehrere Aufgaben Ressourcen teilen können, insbesondere wenn gleichzeitig auf eine Variable zugegriffen wird, muss das Synchronisationsproblem gelöst werden, z.B. ein Multithreading-Bahnfahrkartenverkaufssystem: Ein Befehl überprüft, ob die Tickets verkauft sind, und ein anderer Befehl verkauft gleichzeitig von mehreren Fenstern aus Tickets, was zu dem Problem führen kann, dass nicht existierende Tickets verkauft werden.
Bei parallelen Operationen wird die Reihenfolge der Ausführung von Anweisungen vom Kernel entschieden. Innerhalb desselben Threads werden Anweisungen in der Reihenfolge ausgeführt, aber es ist schwer zu sagen, welche Anweisung in den verschiedenen Threads zuerst ausgeführt wird. Daher muss über das Synchronisationsproblem der Mehrere Threads nachgedacht werden. Synchronisation (Synchronization) bedeutet, dass nur einer Thread in einer bestimmten Zeit auf eine bestimmte Ressource zugreifen darf.
1、thread-Modul
2、threading-Modul
threading.Thread erstellt einen Thread.
Fügen Sie eine Mutex-Sperre hinzu, um zu überprüfen, ob es noch Restkarten gibt und Tickets zu verkaufen, damit nicht der eine Thread gerade überprüft, dass es keine Restkarten gibt, während der andere Thread den Verkauf durchführt.
#! /usr/bin/python #-* coding: utf-8 -* # __author__ ="tyomcat" import threading import time import os def booth(tid): global i global lock while True: lock.acquire() if i!=0: i=i-1 print "Fenster:", tid, ", verbleibende Tickets:", i time.sleep(1) else: print "Thread_id", tid, "No more tickets" os._exit(0) lock.release() time.sleep(1) i = 100 lock=threading.Lock() for k in range(10) new_thread = threading.Thread(target=booth, args=(k,)) new_thread.start()
Zwei, Koroutine (auch bekannt als Mikrothread, Faden)
Koroutines, anders als die preempptive Scheduling von Threads, sind kooperative Scheduling. Koroutines sind ebenfalls Single-Threaded, aber sie ermöglichen es, ursprünglich asynchrone zu verwenden.+Non-human-readable Code, geschrieben in Callback-Style, kann auf eine scheinbar synchrone Weise ausgeführt werden.
1Koroutines können in Python durch Generatoren (Generator) realisiert werden.
Zunächst müssen wir eine solide Verständnis von Generatoren und 'yield' haben.
Der Aufruf einer normalen Python-Funktion beginnt in der Regel mit der ersten Zeile des Funktionscodes und endet mit einem 'return'-Statement, einem Ausnahme oder dem Ende der Funktionsausführung (man kann es auch als impliziten Rückgang auf 'None' betrachten).
Wenn eine Funktion die Kontrolle an den Aufrufer zurückgibt, bedeutet das das Ende. Manchmal kann man Funktionen erstellen, die eine Sequenz erzeugen, um 'seine Arbeit zu speichern', das sind Generatoren (Funktionen, die den Schlüsselwort 'yield' verwenden).
Die Fähigkeit, eine Sequenz zu erzeugen, liegt daran, dass die Funktion nicht wie im allgemeinen Sinne zurückgegeben wird. Der implizite Bedeutung von 'return' ist, dass die Funktion die Kontrolle über den Ausführungscode an den Ort zurückgibt, von dem sie aufgerufen wurde. Während der implizite Bedeutung von 'yield' eine vorübergehende und willkürliche Übertragung der Kontrolle ist, wird unsere Funktion die Kontrolle später zurückgewinnen.
Schauen wir uns das Beispiel des Produzenten an./Beispiel eines Verbrauchers:
#! /usr/bin/python #-* coding: utf-8 -* # __author__ ="tyomcat" import time import sys # Produzent def produce(l): i=0 while 1: if i < 10: l.append(i) yield i i=i+1 time.sleep(1) else: return # Verbraucher def consume(l): p = produce(l) while 1: try: p.next() while len(l) > 0: print l.pop() except StopIteration: sys.exit(0) if __name__ == "__main__": l = [] consume(l)
Wenn das Programm bis zu produce(yield i) führt, gibt es einen Generator zurück und pausiert die Ausführung. Wenn wir p.next() in custom aufrufen, kehrt das Programm zurück zu produce(yield i) und führt fort, so dass Elemente in l hinzugefügt werden, und dann drucken wir l.pop(), bis p.next() die Ausnahme StopIteration auslöst.
2、Stackless Python
3、greenlet-Modul
Die Implementierung basierend auf greenlet hat eine Leistung, die nur unwesentlich hinter Stackless Python zurückbleibt, ist etwa doppelt so langsam wie Stackless Python und fast eine Größenordnung schneller als andere Lösungen. Tatsächlich ist greenlet keine echte parallele Mechanik, sondern wechselt innerhalb desselben Threads zwischen verschiedenen Codeblöcken der Funktionen und führt aus 'Du läufst eine Weile, ich läufst eine Weile' und muss bei der Wechselzeit und dem Wechselort angegeben werden.
4、eventlet-Modul
三、Mehrprozesse
1、Unterprozess (subprocess-Paket)
In Python wird durch das subprocess-Paket ein Unterprozess geforkt und ein externes Programm ausgeführt.
Wenn ein Systembefehl aufgerufen wird, ist der os-Modul der erste zu berücksichtigende Modul. Die Befehle os.system() und os.popen() werden für die Operationen verwendet. Diese beiden Befehle sind jedoch zu einfach und können keine komplexen Operationen wie das Bereitstellen von Eingaben für laufende Befehle oder das Lesen der Ausgabe von Befehlen, das Beurteilen des Laufzustands eines Befehls oder das Verwalten paralleler Befehle usw. durchführen. In diesem Fall kann der Popen-Befehl in subprocess effektiv die erforderlichen Operationen durchführen.
>>> import subprocess >>> command_line = raw_input() ping -c 10 www.baidu.com >>> args = shlex.split(command_line) >>> p = subprocess.Popen(args)
Verwenden Sie subprocess.PIPE, um die Eingaben und Ausgaben mehrerer Unterprozesse zu verbinden und ein Rohr (Pipe) zu bilden:
import subprocess child1 child = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE) child2 child = subprocess.Popen(["wc"], stdin=child1.stdout, stdout=subprocess.PIPE) out = child2.communicate() print(out)
communicate() -Methode liest Daten aus stdout und stderr und gibt sie in stdin ein.
2)、Multiprozessing (multiprocessing-Paket)
(1)、multiprocessing-Paket ist ein Paket zur Verwaltung mehrerer Prozesse in Python. Ähnlich wie threading.Thread kann es mit dem multiprocessing.Process-Objekt ein Prozess erstellen.
Prozesspool (Process Pool) kann mehrere Prozesse erstellen.
apply_async(func,args) Ein Prozess aus dem Prozesspool wird abgerufen, um func auszuführen. args sind die Parameter von func. Es wird ein AsyncResult-Objekt zurückgegeben, auf das das get()-Verfahren aufgerufen werden kann, um das Ergebnis zu erhalten.
close() Der Prozesspool erstellt keine neuen Prozesse mehr
join() Warten auf den Abschluss aller Prozesse im Prozesspool. Es muss vorher das close()-Verfahren auf den Pool aufgerufen werden, um join() aufrufen zu können.
#! /usr/bin/env python # -*- coding:utf-8 -*- # __author__ == "tyomcat" # "Mein Computer hat4prozesse" from multiprocessing import Pool import os, time def lange_arbeitsaufgabe(name): print 'Führe Aufgabe %s (%s)...' % (name, os.getpid()) start = time.time() time.sleep(3) end = time.time() print 'Task %s läuft %0.2f Sekunden.' % (name, (end - start)) if __name__=='__main__': print 'Elternprozess %s.' % os.getpid() p = Pool() for i in range(4) p.apply_async(long_time_task, args=(i,)) print 'Wartet auf Abschluss aller Unterprozesse...' p.close() p.join() print 'Alle Unterprozesse abgeschlossen.'
(2)、多进程共享资源
Durch Shared Memory und Manager-Objekte: Ein Prozess als Server, Manager zur tatsächlichen Aufbewahrung der Ressourcen erstellen.
Andere Prozesse können den Manager über Parameterübergabe oder Adresse erreichen und eine Verbindung herstellen, um auf die Ressourcen des Servers zuzugreifen.
#! /usr/bin/env python # -*- coding:utf-8 -*- # __author__ == "tyomcat" from multiprocessing import Queue,Pool import multiprocessing,time,random def write(q): for value in ['A','B','C','D']: print "Put %s to Queue!" % value q.put(value) time.sleep(random.random()) def read(q,lock): while True: lock.acquire() if not q.empty(): value=q.get(True) print "Get %s from Queue" % value time.sleep(random.random()) else: break lock.release() if __name__ == "__main__": manager=multiprocessing.Manager() q=manager.Queue() p=Pool() lock=manager.Lock() pw=p.apply_async(write,args=(q,)) pr=p.apply_async(read,args=(q,lock)) p.close() p.join() print print "Alle Daten sind geschrieben und gelesen worden"
Vier, asynchron
Sowohl Threads als auch Prozesse verwenden Synchronisationszahlen. Bei Blockierungen sinkt die Leistung erheblich, was die Nutzung der CPU-Potenzialität behindert, Investitionen in Hardware verschwendet und vor allem die Modulierung der Software verhärtet, was eine Trennung unmöglich macht, was nicht förderlich für zukünftige Erweiterungen und Änderungen ist.
Egal, ob Prozess oder Thread, jede Blockierung oder Wechsel erfordert einen Systemaufruf (system call), der CPU dazu bringt, den调度programmierer des Betriebssystems zu laufen, und dann entscheidet der Scheduler, welchen Prozess (Thread) er ausführen soll. Bei einigen Codebereichen, die auf Mutex zugreifen, müssen zwischen mehreren Threads auch Sperren hinzugefügt werden.
Heutzutage basieren die meisten流行的 asynchronen Server auf Ereignisgesteuertem (z.B. nginx).
In einem asynchronen Ereignisgesteuerten Modell wird eine Operation, die zu einem Blockieren führen würde, in eine asynchrone Operation umgewandelt. Die Hauptthread ist für die Initiierung dieser asynchronen Operation und die Verarbeitung ihrer Ergebnisse verantwortlich. Da alle blockierenden Operationen in asynchrone Operationen umgewandelt werden, verbringt der Hauptthread theoretisch die meiste Zeit mit der Verarbeitung tatsächlicher Berechnungsaufgaben und hat weniger Zeit für die Verwaltung von Multithreading, daher ist die Leistung dieses Modells in der Regel besser.
Das ist der gesamte Inhalt dieses Artikels. Wir hoffen, dass er Ihnen bei Ihrem Lernen hilft und wir bitten Sie, die Anleitung zu unterstützen.
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrecht des jeweiligen Eigentümers. Der Inhalt wurde von Internetbenutzern freiwillig und selbstständig hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie urheberrechtlich anstößige Inhalte entdecken, sind Sie herzlich eingeladen, eine E-Mail an notice#w zu senden.3codebox.com (Bitte ersetzen Sie # durch @ beim Senden von E-Mails zur Meldung von Verstößen und stellen Sie relevante Beweise zur Verfügung. Sobald nachgewiesen, wird diese Website die beanstandeten urheberrechtlichen Inhalte sofort löschen.