Maison  >  Article  >  développement back-end  >  Comment résoudre les erreurs de concurrence dangereuses dans les fonctions Python ?

Comment résoudre les erreurs de concurrence dangereuses dans les fonctions Python ?

WBOY
WBOYoriginal
2023-06-24 12:37:441269parcourir

Python est un langage de programmation de haut niveau populaire. Il possède une syntaxe simple et facile à comprendre, une bibliothèque standard riche et un support communautaire open source. Il prend également en charge plusieurs paradigmes de programmation, tels que la programmation orientée objet, la programmation fonctionnelle, etc. Python est notamment largement utilisé dans le traitement des données, l’apprentissage automatique, le calcul scientifique et d’autres domaines.

Cependant, Python rencontre également quelques problèmes en programmation multithread ou multi-processus. L’un d’eux est l’insécurité de la concurrence. Cet article explique comment résoudre les erreurs de concurrence dangereuses dans les fonctions Python sous les aspects suivants.

1. Raisons d'une concurrence non sécurisée

Les raisons d'une concurrence non sécurisée sont souvent liées aux ressources partagées. Les ressources partagées dans les fonctions peuvent être des variables globales, des attributs de classe, des variables de module, des fichiers, etc. Si plusieurs threads ou processus accèdent aux ressources partagées en même temps, des erreurs imprévisibles peuvent se produire. Par exemple, si plusieurs threads modifient la même variable globale en même temps, le résultat final peut ne pas être celui attendu par le programme.

Ce qui suit est un exemple de code :

import threading

counter = 0

def increment():
    global counter
    for i in range(100000):
        counter += 1

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", counter)

Le code ci-dessus crée 10 threads, et chaque thread exécute la fonction increment. La fonction de cette fonction est d'augmenter la variable globale counter 100000 fois. Cependant, en raison du fait que plusieurs threads accèdent à la variable counter en même temps, des conditions de concurrence dangereuses se produiront, ce qui fera que le résultat final n'est pas attendu. increment函数。该函数的作用是将全局变量counter增加100000次。然而,由于多个线程同时访问counter变量,就会出现并发不安全的情况,导致最终的结果并非是预期的。

2.使用互斥锁解决并发不安全的问题

为了解决函数中的并发不安全问题,我们需要使用线程同步技术。其中,互斥锁是一种简单有效的线程同步机制,它可以保证同时只有一个线程可以访问共享资源。当一个线程获取到互斥锁后,其他试图获取该锁的线程就会被阻塞,直到该线程释放锁。

以下是修改后的代码,使用互斥锁解决上述示例中的并发不安全问题:

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    for i in range(100000):
        lock.acquire()
        counter += 1
        lock.release()

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", counter)

在上述代码中,我们创建了一个threading.Lock()对象,用于实现互斥锁。在修改全局变量counter时,首先要获取锁,然后再释放锁。这样,就确保了同一时间只有一个线程可以修改全局变量,避免了并发不安全的问题。

3.使用线程安全的数据结构

除了使用互斥锁之外,我们还可以使用线程安全的数据结构来避免并发不安全的问题。Python提供了一些线程安全的数据结构,例如queue.Queuecollections.dequethreading.local等。这些数据结构都是线程安全的,可以在多线程环境下安全地使用。

以下是同样的示例代码,使用Python标准库中的queue.Queue替换全局变量counter,从而实现了线程安全:

import threading
import queue

q = queue.Queue()

def increment():
    for i in range(100000):
        q.put(1)

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

print("counter:", q.qsize())

在上述代码中,我们创建了一个queue.Queue()对象,用于存储任务。在每个线程中,我们向队列中放入100000个任务(即数字1)。最后,我们统计队列中任务的数量,就可以得到正确的结果。由于queue.Queue

2. Utilisez des verrous mutex pour résoudre les problèmes de concurrence dangereux

Afin de résoudre les problèmes de concurrence dangereux dans les fonctions, nous devons utiliser la technologie de synchronisation des threads. Parmi eux, le verrouillage mutex est un mécanisme de synchronisation de threads simple et efficace, qui peut garantir qu'un seul thread peut accéder aux ressources partagées en même temps. Lorsqu'un thread acquiert un verrou mutex, les autres threads tentant d'acquérir le verrou seront bloqués jusqu'à ce que le thread libère le verrou.

Ce qui suit est le code modifié qui utilise des verrous mutex pour résoudre le problème de concurrence non sécurisée dans l'exemple ci-dessus : 🎜rrreee🎜Dans le code ci-dessus, nous créons un objet threading.Lock(), en utilisant To implémenter un verrou mutex. Lors de la modification de la variable globale counter, vous devez d'abord acquérir le verrou puis libérer le verrou. De cette façon, on garantit qu'un seul thread peut modifier les variables globales en même temps, évitant ainsi les problèmes de concurrence dangereux. 🎜🎜3. Utilisez des structures de données thread-safe🎜🎜En plus d'utiliser des verrous mutex, nous pouvons également utiliser des structures de données thread-safe pour éviter les problèmes de concurrence dangereux. Python fournit des structures de données thread-safe, telles que queue.Queue, collections.deque, threading.local, etc. Ces structures de données sont thread-safe et peuvent être utilisées en toute sécurité dans des environnements multithread. 🎜🎜Ce qui suit est le même exemple de code, utilisant le queue.Queue de la bibliothèque standard Python pour remplacer la variable globale counter, assurant ainsi la sécurité des threads : 🎜rrreee🎜In Avec le code ci-dessus, nous avons créé un objet queue.Queue() pour stocker les tâches. Dans chaque thread, nous mettons 100 000 tâches (c'est-à-dire le numéro 1) dans la file d'attente. Enfin, nous pouvons obtenir le résultat correct en comptant le nombre de tâches dans la file d'attente. Étant donné que queue.Queue est thread-safe, plusieurs threads peuvent placer des tâches dans la file d'attente en même temps sans provoquer de problèmes de concurrence dangereux. 🎜🎜4. Conclusion🎜🎜Cet article présente le problème de la concurrence non sécurisée dans les fonctions Python et comment utiliser les verrous mutex et les structures de données thread-safe pour résoudre ce problème. Le verrouillage Mutex est un mécanisme de synchronisation de threads simple et efficace qui garantit qu'un seul thread peut accéder aux ressources partagées en même temps ; les structures de données thread-safe peuvent être utilisées en toute sécurité dans des environnements multithread. Dans la programmation réelle, nous devons prêter attention à la manière d'utiliser ces technologies pour garantir l'exactitude et la stabilité du programme. 🎜

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