Maison  >  Article  >  développement back-end  >  Comment résoudre l’erreur de synchronisation multithread de Python ?

Comment résoudre l’erreur de synchronisation multithread de Python ?

WBOY
WBOYoriginal
2023-06-24 18:26:461231parcourir

Le problème de synchronisation multi-thread de Python est un problème courant lors de l'écriture de programmes simultanés. Bien que Python dispose d'un module de threading intégré, le multithreading de Python n'est pas une exécution véritablement parallèle en raison de l'existence du Global Interpreter Lock (GIL). Mais dans certains cas, il est encore nécessaire d’utiliser le multi-threading pour améliorer l’efficacité des programmes Python. Cet article présentera plusieurs méthodes pour résoudre les problèmes de synchronisation multithread Python.

1. Utilisez le mécanisme de verrouillage

Lock est un mécanisme en Python pour synchroniser l'accès multithread aux ressources partagées. Lorsque plusieurs threads effectuent des opérations de lecture et d'écriture sur des ressources partagées, si aucune mesure n'est prise, une concurrence de données et des résultats incohérents se produiront. Par conséquent, des verrous sont nécessaires pour garantir qu'un seul thread accède aux ressources partagées à la fois.

Il existe deux mécanismes de verrouillage en Python : RLock et Lock. Parmi eux, Lock est plus efficace, mais des problèmes de blocage se produiront lorsque les verrous seront détenus à plusieurs reprises. RLock prend en charge la possession répétée de verrous, mais l'efficacité est légèrement inférieure à celle de Lock. Voici un exemple d'utilisation de Lock :

import threading

count = 0
lock = threading.Lock()

def hello():
    global count
    lock.acquire()
    for i in range(1000000):
        count += 1
    lock.release()

t1 = threading.Thread(target=hello)
t2 = threading.Thread(target=hello)
t1.start()
t2.start()
t1.join()
t2.join()
print(count)

Lock est utilisé ici pour protéger l'opération de mise à jour de la variable partagée count, évitant ainsi les problèmes de synchronisation causés par l'accès de plusieurs threads à count en même temps.

2. Utiliser des variables de condition

Les variables de condition sont un mécanisme de communication entre les threads. Elles sont utilisées entre les threads pour attendre qu'une certaine condition se produise, puis notifier les autres threads. Dans la bibliothèque de threads intégrée de Python, vous pouvez utiliser threading.Condition pour créer des variables de condition.

L'exemple suivant utilise des variables de condition pour implémenter un modèle producteur-consommateur :

import threading
import time

queue = []
MAX_NUM = 5
condition = threading.Condition()

class ProducerThread(threading.Thread):
    def run(self):
        nums = range(5)
        global queue
        while True:
            condition.acquire()
            if len(queue) == MAX_NUM:
                print("队列已满,生产者等待")
                condition.wait()
                print("生产者被唤醒")
            num = nums.pop()
            queue.append(num)
            print("生产者生产了", num)
            condition.notifyAll()
            condition.release()
            time.sleep(1)


class ConsumerThread(threading.Thread):
    def run(self):
        global queue
        while True:
            condition.acquire()
            if not queue:
                print("队列为空,消费者等待")
                condition.wait()
                print("消费者被唤醒")
            num = queue.pop(0)
            print("消费者消费了", num)
            condition.notifyAll()
            condition.release()
            time.sleep(2)

if __name__ == '__main__':
    t1 = ProducerThread()
    t2 = ConsumerThread()
    t1.start()
    t2.start()
    t1.join()
    t2.join()

Dans cet exemple, les variables de condition sont utilisées pour contrôler l'exécution des producteurs et des consommateurs. Le thread producteur attendra lorsque la file d’attente est pleine et le thread consommateur attendra lorsque la file d’attente est vide. Lorsque de nouvelles données sont produites ou consommées, les autres threads en attente seront avertis via la méthode notifyAll().

3. Utiliser des files d'attente

La file d'attente est une structure de données thread-safe qui peut être utilisée pour réaliser la synchronisation et la communication entre les threads. En Python, le module de file d'attente fournit deux classes de file d'attente qui prennent en charge le multithreading : Queue et LifoQueue. La première est une file d'attente premier entré, premier sorti, et la seconde est une file d'attente dernier entré, premier sorti. L'utilisation de Queue peut éviter le problème de l'écriture vous-même de verrous et de variables de condition.

L'exemple suivant utilise Queue pour implémenter un modèle producteur-consommateur :

import threading
import time
import queue

q = queue.Queue()

class ProducerThread(threading.Thread):
    def run(self):
        nums = range(5)
        global q
        for num in nums:
            q.put(num)
            print("生产者生产了", num)
            time.sleep(1)


class ConsumerThread(threading.Thread):
    def run(self):
        global q
        while True:
            num = q.get()
            q.task_done()
            print("消费者消费了", num)
            time.sleep(2)

if __name__ == '__main__':
    t1 = ProducerThread()
    t2 = ConsumerThread()
    t1.start()
    t2.start()
    t1.join()
    t2.join()

Dans cet exemple, Queue est utilisé comme tampon entre le producteur et le consommateur. Le thread producteur produit des données et les place dans la file d'attente, le consommateur. le thread extrait les données de la file d’attente pour les consommer. Les méthodes put() et get() de Queue sont thread-safe et n'ont pas besoin d'utiliser de verrous ou de variables de condition pour la synchronisation.

En bref, bien que la programmation multithread de Python ne soit pas une véritable exécution parallèle, elle peut améliorer l'efficacité du programme pour certaines tâches gourmandes en E/S. Cependant, lors de l'écriture de programmes multithread, une attention particulière doit être accordée aux problèmes de synchronisation et de communication entre les threads afin d'éviter des problèmes tels que des conditions de concurrence critique et des blocages. Les problèmes de synchronisation multithread peuvent être résolus grâce à des mécanismes tels que des verrous, des variables de condition et des files d'attente.

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!

Déclaration:
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