web-dev-qa-db-fra.com

Python conteneurs intégrés sont-ils thread-safe?)

Je voudrais savoir si les conteneurs intégrés Python (liste, vecteur, ensemble ...) sont thread-safe? Ou dois-je implémenter un environnement de verrouillage/déverrouillage pour mon partage variable?

54
Phong

Vous devez implémenter votre propre verrouillage pour toutes les variables partagées qui seront modifiées en Python. Vous n'avez pas à vous soucier de la lecture des variables qui ne seront pas modifiées (c'est-à-dire que les lectures simultanées sont correctes), donc les types immuables (frozenset, Tuple, str) sont probablement sûrs, mais cela ne ferait pas de mal. Pour les choses que vous allez changer - list, set, dict, et la plupart des autres objets, vous devriez avoir votre propre mécanisme de verrouillage (alors que les opérations sur place sont ok sur la plupart d'entre eux, les threads peuvent conduire à des bugs super-méchants - vous pourriez aussi bien implémenter le verrouillage, c'est assez facile).

Soit dit en passant, je ne sais pas si vous le savez, mais le verrouillage est très facile dans Python - créez un objet threading.lock, puis vous pouvez l'acquérir/le libérer comme ceci:

import threading
list1Lock = threading.Lock()

with list1Lock:
    # change or read from the list here
# continue doing other stuff (the lock is released when you leave the with block)

Dans Python 2.5, faites from __future__ import with_statement; Python 2.4 et avant ne l'ont pas, vous voudrez donc mettre les appels d'acquisition ()/release () dans try:...finally: blocs:

import threading
list1Lock = threading.Lock()

try:
    list1Lock.acquire()
    # change or read from the list here
finally:
    list1Lock.release()
# continue doing other stuff (the lock is released when you leave the with block)

Quelques très bonnes informations sur la synchronisation des threads en Python .

44
Daniel G

Oui, mais vous devez bien sûr faire attention

Par exemple:

Si deux threads se précipitent vers pop() à partir d'une liste avec un seul élément, un thread obtiendra l'élément avec succès et l'autre obtiendra un IndexError

Un code comme celui-ci n'est pas thread-safe

if L:
    item=L.pop() # L might be empty by the time this line gets executed

Tu devrais l'écrire comme ça

try:
    item=L.pop()
except IndexError:
    # No items left
10
John La Rooy

Ils sont thread-safe tant que vous ne désactivez pas le code GIL en C pour le thread.

5

Le module de file d'attente implémente des files d'attente multi-producteurs et multi-consommateurs. Il est particulièrement utile dans la programmation threadée lorsque les informations doivent être échangées en toute sécurité entre plusieurs threads. La classe Queue de ce module implémente toutes les sémantiques de verrouillage requises.

https://docs.python.org/3/library/queue.html

0
Ronit Goldental