Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der Synchronisationssperre im Python-Thread

Detaillierte Erläuterung der Synchronisationssperre im Python-Thread

不言
不言Original
2018-04-27 10:01:311461Durchsuche

In diesem Artikel werden hauptsächlich die relevanten Informationen zu Synchronisationssperren in Python-Threads ausführlich vorgestellt, die einen bestimmten Referenzwert haben.

In Anwendungen mit Multithreads: So stellen Sie die Thread-Sicherheit sicher. Die Synchronisierung zwischen Threads oder der Zugriff auf gemeinsam genutzte Variablen sind ebenfalls Probleme, wenn sie nicht richtig gehandhabt werden. Verwenden Sie die Python-Semaphor-Ereignisbedingung Gewährleisten Sie die Synchronisierung zwischen Threads, und letzteres gewährleistet den gegenseitigen Ausschluss des Zugriffs auf gemeinsam genutzte Variablen

Lock & RLock: Mutex-Sperren werden verwendet, um den Multi-Thread-Zugriff auf gemeinsam genutzte Variablen sicherzustellen
Semaphore-Objekt: eine erweiterte Version von Sperrmutex, der mehreren Threads gleichzeitig gehören kann, während die Sperre nur einem bestimmten Thread gleichzeitig gehören kann.
Ereignisobjekt: Es handelt sich um eine Kommunikationsmethode zwischen Threads, die einem Signal entspricht. Ein Thread kann ein Signal an einen anderen Thread senden und diesen dann eine Operation ausführen lassen.
Bedingungsobjekt: Es kann Daten nur verarbeiten, nachdem bestimmte Ereignisse ausgelöst oder bestimmte Bedingungen erfüllt sind

1. Sperre (Mutex-Sperre)

Sperre anfordern – Enter den Sperrenpool und warten – Sperre erwerben – Gesperrt – Sperre freigeben

Sperren (Befehlssperre) ist der niedrigste verfügbare Synchronisierungsbefehl. Wenn sich Lock im gesperrten Zustand befindet, gehört es keinem bestimmten Thread. Lock enthält zwei Zustände – gesperrt und nicht gesperrt – sowie zwei grundlegende Methoden.

Es kann davon ausgegangen werden, dass Lock über einen Sperrpool verfügt. Wenn ein Thread eine Sperre anfordert, wird der Thread im Pool platziert, bis er nach Erhalt der Sperre aus dem Pool freigegeben wird. Threads im Pool befinden sich im Zustandsdiagramm im synchronen Blockierungszustand.

Konstruktionsmethode:
Lock()

Instanzmethode:
acquire([timeout]): Versetzen Sie den Thread in den Synchronisierungsblockierungszustand und versuchen Sie es Holen Sie sich die Sperre.
release(): Sperre freigeben. Der Thread muss die Sperre vor der Verwendung erworben haben, andernfalls wird eine Ausnahme ausgelöst.

if mutex.acquire():
 counter += 1
 print "I am %s, set counter:%s" % (self.name, counter)
  mutex.release()

2. RLock (reentrant lock)

RLock (reentrant lock) ist eine mehrfach angeforderte Synchronisierungsanweisung vom selben Thread. RLock verwendet die Konzepte „eigener Thread“ und „Rekursionsebene“. Im gesperrten Zustand gehört RLock einem Thread. Der Thread, der die RLock besitzt, kann acquire() erneut aufrufen und muss release() genauso oft aufrufen, um die Sperre aufzuheben.

Es kann davon ausgegangen werden, dass RLock einen Sperrpool und einen Zähler mit einem Anfangswert von 0 enthält. Bei jedem erfolgreichen Aufruf von acquire()/release() wird der Zähler um +1/-1 erhöht , und wenn es 0 ist, befindet sich das Schloss im Status „Entsperrt“.

Konstruktionsmethode:
RLock()

Instanzmethode:
acquire([timeout])/release(): Ähnlich wie Lock.

3. Semaphore (gemeinsamer Objektzugriff)

Um ehrlich zu sein, ist Semaphore die neueste Synchronisationssperre, die ich in der Vergangenheit verwendet habe Ich habe Rlock zur Implementierung verwendet, was relativ kompliziert ist. Schließlich erfordert Rlock das paarweise Sperren und Entsperren. . .

Semaphore verwaltet einen integrierten Zähler.
Der integrierte Zähler ist -1, wenn „acquire()“ aufgerufen wird.
Der integrierte Zähler ist +1, wenn „release()“ aufgerufen wird.
Der Zähler darf nicht kleiner als 0 sein. Wenn der Zähler 0 ist, blockiert acquire() den Thread, bis ein anderer Thread release() aufruft.

Gehen Sie direkt zum Code, wir steuern das Semaphor auf 3, das heißt, 3 Threads können diese Sperre gleichzeitig verwenden, und die verbleibenden Threads können nur blockieren und warten ...

#coding:utf-8
#blog xiaorui.cc
import time
import threading

semaphore = threading.Semaphore(3)

def func():
 if semaphore.acquire():
  for i in range(3):
   time.sleep(1)
   print (threading.currentThread().getName() + '获取锁')
  semaphore.release()
  print (threading.currentThread().getName() + ' 释放锁')


for i in range(5):
 t1 = threading.Thread(target=func)
 t1.start()

4. Ereignis (Kommunikation zwischen Threads)

Ereignis enthält intern ein Flag, das zunächst falsch ist.
Sie können set() verwenden, um es auf true zu setzen;
Sie können is_set() verwenden, um den Status des Flag-Bits zu überprüfen;

Eine weitere wichtige Funktion ist wait(timeout=None), die zum Blockieren des aktuellen Threads verwendet wird, bis das interne Flag-Bit des Ereignisses auf true gesetzt wird oder das Timeout abläuft. Wenn das interne Flag wahr ist, versteht die Funktion wait() und gibt zurück.

rrree

5. Bedingung (Thread-Synchronisation)

Bedingung kann als erweiterter Thread verstanden werden Funktionen als Lock und RLock, die es uns ermöglichen, komplexe Thread-Synchronisierungsprobleme zu kontrollieren. threadiong.Condition verwaltet intern ein Threadion-Objekt (der Standardwert ist RLock), das beim Erstellen eines Condigtion-Objekts als Parameter übergeben werden kann. Condition stellt auch Erwerbs- und Freigabemethoden bereit, deren Bedeutung mit den Erwerbs- und Freigabemethoden des Hosts übereinstimmt. Tatsächlich rufen sie einfach die entsprechenden Methoden des internen Hostobjekts auf. Condition stellt außerdem die folgenden Methoden bereit (besonderer Hinweis: Diese Methoden können nur nach dem Erwerb aufgerufen werden, andernfalls wird eine RuntimeError-Ausnahme gemeldet.):

Condition.wait([ timeout]):
Die Wartemethode gibt den belegten internen Speicher frei und der Thread wird angehalten, bis er nach Erhalt einer Benachrichtigung oder einer Zeitüberschreitung aktiviert wird (sofern der Timeout-Parameter angegeben ist). Wenn der Thread aufgeweckt wird und den Thread erneut belegt, wird das Programm weiter ausgeführt.

Condition.notify():
Weckt einen angehaltenen Thread auf (falls ein angehaltener Thread vorhanden ist). Hinweis: Die Methode notify() gibt den belegten Speicher nicht frei.

Condition.notify_all()
Condition.notifyAll()

唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

对于Condition有个例子,大家可以观摩下。

from threading import Thread, Condition
import time
import random

queue = []
MAX_NUM = 10
condition = Condition()

class ProducerThread(Thread):
 def run(self):
  nums = range(5)
  global queue
  while True:
   condition.acquire()
   if len(queue) == MAX_NUM:
    print "Queue full, producer is waiting"
    condition.wait()
    print "Space in queue, Consumer notified the producer"
   num = random.choice(nums)
   queue.append(num)
   print "Produced", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


class ConsumerThread(Thread):
 def run(self):
  global queue
  while True:
   condition.acquire()
   if not queue:
    print "Nothing in queue, consumer is waiting"
    condition.wait()
    print "Producer added something to queue and notified the consumer"
   num = queue.pop(0)
   print "Consumed", num
   condition.notify()
   condition.release()
   time.sleep(random.random())


ProducerThread().start()
ConsumerThread().start()

相关推荐:

python多线程之事件Event的使用详解

python线程池threadpool的实现

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Synchronisationssperre im Python-Thread. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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