Analyse von Missverständnissen über die Verwendung von Blockierung (Join) und Sperre (Lock) im Python-Multithreading

不言
Freigeben: 2018-04-27 10:53:31
Original
3000 Leute haben es durchsucht

Dieser Artikel ist hauptsächlich für alle zum Detail gedacht Es führt zu Missverständnissen über das Blockieren von Join und Lock in Python-Multithreading, die einen gewissen Referenzwert haben. Interessierte Freunde können sich auf

Über das Blockieren des Hauptthreads

Falsch beziehen Die Verwendung von Join

Thread.join() dient dazu, den Hauptthread zu blockieren. Das heißt, wenn der untergeordnete Thread nicht zurückkehrt, wartet der Hauptthread auf seine Rückkehr, bevor er mit der Ausführung fortfährt.

Join kann nicht mit Start in einer Schleife verwendet werden
Das Folgende ist der Fehlercode. Der Code erstellt 5 Threads und verwendet dann eine Schleife, um die Threads zu aktivieren.

threads = [Thread() for i in range(5)]
for thread in threads:
  thread.start()
  thread.join()
Nach dem Login kopieren

Ausführungsprozess:

1. In der ersten Schleife aktiviert der Hauptthread Thread 1 über die Startfunktion und den Thread 1 führt Berechnungen durch.
2. Da die Startfunktion den Hauptthread nicht blockiert, führt der Hauptthread die Join-Funktion nach unten aus.
3 von Thread 1. Bevor Thread 1 das Ergebnis zurückgibt, kann der Hauptthread den nächsten Zyklus nicht ausführen
4. Aktiviert Thread 2 und wird von ihm blockiert ...

Auf diese Weise ist ersichtlich, dass die fünf Threads, die gleichzeitig sein sollten, hier zu sequentiellen Warteschlangen geworden sind und die Effizienz dieselbe ist wie die von ein einzelner Thread.

Die korrekte Verwendung von Join

Verwenden Sie zwei Schleifen, um die Funktionen

start bzw. join zu verarbeiten . Parallelität kann erreicht werden

threads = [Thread() for i in range(5)]
for thread in threads:
  thread.start()
for thread in threads:
  thread.join()
Nach dem Login kopieren

time.sleep ersetzt Join zum Debuggen

Ich habe solchen Code bereits in einigen Projekten gesehen, der Zeit verwendet .sleep statt beizutreten, um den Hauptthread manuell zu blockieren.

Bevor alle untergeordneten Threads zurückkehren, wird der Hauptthread zu einer drahtlosen Schleife und kann nicht beendet werden.

for thread in threads:
  thread.start()
while 1:
  if thread_num == 0:
    break
  time.sleep(0.01)
Nach dem Login kopieren

Über Thread-Sperre (threading.Lock)

Ob Single-Core-CPU+PIL Benötigen Sie noch eine Sperre?

Nichtatomare Operation

Anzahl = Anzahl + 1 Theoretisch ist es threadunsicher. Verwenden Sie 3 Threads, um den Wert der globalen Variablenanzahl gleichzeitig zu ändern. Und überprüfen Sie die Ergebnisse der Programmausführung korrekt ist, bedeutet dies, dass kein Thread-Konflikt auftritt.

Verwenden Sie den folgenden Code zum Testen

# -*- coding: utf-8 -*-
import threading
import time
count = 0
class Counter(threading.Thread):
  def __init__(self, name):
    self.thread_name = name
    super(Counter, self).__init__(name=name)
  def run(self):
    global count
    for i in xrange(100000):
      count = count + 1
counters = [Counter('thread:%s' % i) for i in range(5)]
for counter in counters:
  counter.start()
time.sleep(5)
print 'count=%s' % count
Nach dem Login kopieren

Ausführungsergebnis:

count=275552

Tatsächlich sind die Ergebnisse jedes Laufs unterschiedlich und falsch, was beweist, dass Single-Core-CPU+PIL immer noch keine Thread-Sicherheit garantieren kann.

Korrekter Code nach dem Sperren:

# -*- coding: utf-8 -*-
import threading
import time
count = 0
lock = threading.Lock()
class Counter(threading.Thread):
  def __init__(self, name):
    self.thread_name = name
    self.lock = threading.Lock()
    super(Counter, self).__init__(name=name)
  def run(self):
    global count
    global lock
    for i in xrange(100000):
      lock.acquire()
      count = count + 1
      lock.release()


counters = [Counter('thread:%s' % i) for i in range(5)]

for counter in counters:
  counter.start()

time.sleep(5)
print 'count=%s' % count
Nach dem Login kopieren

Ergebnis:

count=500000

Achten Sie auf die globale Natur der Sperre

Dies ist ein einfaches Python-Syntaxproblem, das jedoch ignoriert werden kann, wenn die Logik komplex ist.

Stellen Sie sicher, dass die Sperre häufig vorkommt mehrere Unterthreads, das heißt, es werden keine Sperren innerhalb der Thread-Unterklasse erstellt.


Die folgenden sind

Fehlercodes

# -*- coding: utf-8 -*-

import threading
import time
count = 0
# lock = threading.Lock() # 正确的声明位置
class Counter(threading.Thread):
  def __init__(self, name):
    self.thread_name = name
    self.lock = threading.Lock() # 错误的声明位置
    super(Counter, self).__init__(name=name)
  def run(self):
    global count
    for i in xrange(100000):
      self.lock.acquire()
      count = count + 1
      self.lock.release()
counters = [Counter('thread:%s' % i) for i in range(5)]

for counter in counters:
  print counter.thread_name
  counter.start()

time.sleep(5)
print 'count=%s' % count
Nach dem Login kopieren

Verwandte Empfehlungen:


Detaillierte Erläuterung der Synchronisationssperren in Python-Threads

Python-Multithreading-Ereignisse im Detail Erläuterung der Verwendung von Event

Implementierung des Python-Thread-Pools Threadpool

Das obige ist der detaillierte Inhalt vonAnalyse von Missverständnissen über die Verwendung von Blockierung (Join) und Sperre (Lock) im Python-Multithreading. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage