Heim > Artikel > Backend-Entwicklung > Detaillierte Erläuterung der einfachen Verwendung von Python-Multithreading, Sperren und Ereignismechanismen
Dieser Artikel stellt hauptsächlich die einfache Verwendung von Python-Multithreading, Sperren und Ereignismechanismen vor. Jetzt teile ich ihn mit Ihnen und gebe ihm eine Referenz. Werfen wir gemeinsam einen Blick darauf
Threads und Prozesse
1. Ein Thread teilt den Adressraum des Prozesses, der ihn erstellt hat. und der Prozess verfügt über einen eigenen Adressraum
2. Threads können auf alle Daten des Prozesses zugreifen, und Threads können auf einander zugreifen
3. Die Daten zwischen Threads sind unabhängig
4. Der untergeordnete Prozess kopiert die Daten des Threads
5. Der untergeordnete Prozess ist unabhängig, nachdem er gestartet wurde. Der übergeordnete Prozess kann den untergeordneten Prozess nur beenden, aber keine Daten austauschen >6. Ändern Sie die Daten im Thread. Alle wirken sich auf andere Threads aus, und Änderungen am Prozess wirken sich nicht auf den untergeordneten Prozess aus >
Thread ist ein Threading-Modul. Eine der wichtigsten Klassen in , mit der Sie Threads erstellen können. Es gibt zwei Möglichkeiten, einen Thread zu erstellen: Eine besteht darin, die Thread-Klasse zu erben und ihre Ausführungsmethode zu überschreiben. Die andere besteht darin, ein threading.Thread-Objekt zu erstellen und das aufrufbare Objekt als Parameter in seine Initialisierungsfunktion (__init__) einzugeben.Sehen wir uns zunächst ein Beispiel für die Erstellung eines Threads durch Vererbung der Threading.Thread-Klasse an:
import threading import time class MyThread(threading.Thread): def __init__(self, arg): # super(MyThread, self).__init__() # 新式类继承原有方法写法 threading.Thread.__init__(self) self.arg = arg def run(self): time.sleep(2) print(self.arg) for i in range(10): thread = MyThread(i) print(thread.name) thread.start()
import threading import time def process(arg): time.sleep(2) print(arg) for i in range(10): t = threading.Thread(target=process, args=(i,)) print(t.name) t.start()
Die Thread-Klasse definiert außerdem die folgenden allgemeinen Methoden und Attribute:
Thread.getName() Get the Thread-Name
Thread.setName() Setzt den Thread-NamenThread.name Thread-Name
Thread.ident Den Bezeichner von abrufen der Thread. Die Thread-ID ist eine Ganzzahl ungleich Null. Dieses Attribut ist nur gültig, nachdem die start()-Methode aufgerufen wurde. Andernfalls wird nur None
Thread.is_alive()
Thread.join([timeout]) Der Aufruf von Thread.join blockiert den aufrufenden Thread, bis der aufgerufene Thread endet oder eine Zeitüberschreitung auftritt. Der Parameter timeout ist ein numerischer Typ, der die Timeout-Zeit angibt. Wenn dieser Parameter nicht angegeben wird, wird der aufrufende Hauptthread blockiert, bis der aufgerufene Thread endet
Python GIL (Global Interpreter Lock). )
# 锁:GIL 全局解释器 它是为了保证线程在运行过程中不被抢占 number = 0 lock = threading.RLock() # 创建锁 def run(num): lock.acquire() # 加锁 global number number += 1 print(number) time.sleep(2) lock.release() # 释放锁 for i in range(10): t = threading.Thread(target=run, args=(i, )) t.start()
Join & Daemon
Im Hauptthread A wird Unterthread B erstellt und B.setDaemon() im Hauptthread A aufgerufen. Dies bedeutet, dass Hauptthread A zu diesem Zeitpunkt als Daemon-Thread festgelegt ist endet, unabhängig davon, ob Sub-Thread B abgeschlossen ist, wird er mit Haupt-Thread A beendet. Dies ist die Bedeutung der setDaemon-Methode, die im Grunde das Gegenteil von Join ist. Darüber hinaus ist noch etwas Besonderes zu beachten: Sie muss vor dem Aufruf der start()-Methode festgelegt werden. Wenn sie nicht als Daemon-Thread festgelegt ist, wird das Programm auf unbestimmte Zeit angehalten.
class MyThread1(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print("thread start") time.sleep(3) print('thread end') print('main start') thread1 = MyThread1() # thread1.setDaemon(True) # 设置子线程是否跟随主线程一起结束 thread1.start() time.sleep(1) print('satrt join') # thread1.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程 print('end join')
def run(n): print('[%s]------running----\n' % n) time.sleep(2) print('--done--') def main(): for i in range(5): t = threading.Thread(target=run, args=[i,]) t.start() # t.join() print('starting thread', t.getName()) m = threading.Thread(target=main,args=[]) # m.setDaemon(True) # 将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务 m.start() # m.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程 print("---main thread done----")
Thread Lock (Mutex)
Mehrere Threads können unter einem Prozess gestartet werden, und mehrere Threads teilen sich den Speicherplatz des übergeordneten Prozesses, was bedeutet, dass jeder Thread zu diesem Zeitpunkt auf dieselben Daten zugreifen kann, wenn zwei Threads gleichzeitig dieselben Daten ändern möchten Zeit, was wird passieren?
num = 100 # 设定一个共享变量 def subNum(): global num # 在每个线程中都获取这个全局变量 print('--get num:', num) time.sleep(2) num -= 1 # 对此公共变量进行-1操作 thread_list = [] for i in range(100): t = threading.Thread(target=subNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有线程执行完毕 t.join() print('final num:', num)
# 加锁版本 def subNum(): global num # 在每个线程中都获取这个全局变量 print('--get num:', num) time.sleep(1) lock.acquire() # 修改数据前加锁 num -= 1 # 对此公共变量进行-1操作 lock.release() # 修改后释放 num = 100 # 设定一个共享变量 thread_list = [] lock = threading.Lock() # 生成全局锁 for i in range(100): t = threading.Thread(target=subNum) t.start() thread_list.append(t) for t in thread_list: # 等待所有线程执行完毕 t.join() print('final num:', num)
Der Unterschied zwischen Rlock und Lock:
RLock ermöglicht die mehrfache Erfassung im selben Thread. Aber Lock lässt dies nicht zu. Andernfalls entsteht eine Endlosschleife und das Programm weiß nicht, welche Sperre aufgehoben werden soll. Hinweis: Wenn Sie RLock verwenden, müssen Acquire und Release paarweise erscheinen, d. h. nach dem Aufruf von Acquire n-mal muss Release n-mal aufgerufen werden, um die belegte Sperre wirklich freizugeben
Events
Python stellt das Event-Objekt für die Kommunikation zwischen Threads bereit. Es handelt sich um ein vom Thread gesetztes Signal-Flag, warten andere Threads, bis das Signal kontaktiert wird.
1 Signal setzenevent.set()
Wenn die set()-Methode des Ereignisobjekts verwendet wird, gibt die isSet()-Methode true zurück
event.clear()
使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,isSet()方法返回假
3 等待
event.wait()
Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回。当Event对象的内部信号标志位假时,
则wait方法一直等待到其为真时才返回。也就是说必须set新号标志位真
def do(event): print('start') event.wait() print('execute') event_obj = threading.Event() for i in range(10): t = threading.Thread(target=do, args=(event_obj,)) t.start() event_obj.clear() inp = input('输入内容:') if inp == 'true': event_obj.set()
相关推荐:
Python多线程中阻塞(join)与锁(Lock)使用误区解析
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der einfachen Verwendung von Python-Multithreading, Sperren und Ereignismechanismen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!