Partager les données en toute sécurité
Utiliser des files et des verrous
Partager les données en toute sécurité est une leçon Python Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Python Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Python Academy comprend 4 leçons au total.
Le problème des conditions de concurrence
Lorsque plusieurs threads modifient les mêmes données, leurs opérations peuvent s'entrelacer et corrompre le résultat. Il s'agit d'une condition de concurrence. Nous avons besoin d'outils de synchronisation pour partager les données en toute sécurité.
import threading
counter = 0
def bump():
global counter
for _ in range(100000):
counter += 1
ts = [threading.Thread(target=bump) for _ in range(2)]
for t in ts: t.start()
for t in ts: t.join()
print('counter (may be < 200000):', counter)Lock à la rescousse
Un threading.Lock garantit qu'un seul thread à la fois entre dans une section critique. Acquérez-le avec un bloc with autour de la mise à jour partagée.
import threading
counter = 0
lock = threading.Lock()
def bump():
global counter
for _ in range(100000):
with lock:
counter += 1
ts = [threading.Thread(target=bump) for _ in range(2)]
for t in ts: t.start()
for t in ts: t.join()
print('counter:', counter)acquire et release
Un verrou peut être utilisé manuellement avec acquire() et release(), mais la forme with est plus sûre, car elle libère le verrou même en cas d'erreur.
import threading
lock = threading.Lock()
lock.acquire()
try:
print('inside critical section')
finally:
lock.release()
print('released')Files d'attente sûres pour les threads
La classe queue.Queue est déjà sûre pour les threads. Les threads peuvent appeler put et get sans verrous explicites, ce qui en fait la méthode privilégiée pour transmettre des données.
import queue, threading
q = queue.Queue()
def producer():
for i in range(3):
q.put(i)
t = threading.Thread(target=producer)
t.start()
t.join()
while not q.empty():
print('got', q.get())Producer et Consumer
Le schéma classique : les producteurs placent le travail dans une file d'attente avec put, et les consommateurs le récupèrent avec get avant de le traiter. La file d'attente gère tous les verrous.
import queue, threading
q = queue.Queue()
results = []
def consumer():
while True:
item = q.get()
if item is None:
break
results.append(item * 10)
q.task_done()
t = threading.Thread(target=consumer)
t.start()
for i in range(3):
q.put(i)
q.put(None)
t.join()
print(results)join et task_done
q.join() bloque jusqu'à ce que chaque élément placé avec put ait reçu un appel correspondant à task_done(). Le thread principal peut ainsi attendre la fin de tout le travail.
import queue, threading
q = queue.Queue()
def worker():
while True:
item = q.get()
q.task_done()
threading.Thread(target=worker, daemon=True).start()
for i in range(5):
q.put(i)
q.join()
print('all items processed')RLock pour la réentrance
Un Lock ordinaire provoque un interblocage si le même thread tente de l'acquérir deux fois. Un threading.RLock (verrou réentrant) l'autorise en comptant les acquisitions.
import threading
rlock = threading.RLock()
def outer():
with rlock:
inner()
def inner():
with rlock:
print('re-entered safely')
outer()Event pour la signalisation
Un threading.Event permet à un thread d'envoyer un signal aux autres. Les threads appellent wait() jusqu'à ce qu'un autre appelle set().
import threading
start = threading.Event()
def worker():
start.wait()
print('go!')
t = threading.Thread(target=worker)
t.start()
print('setting event')
start.set()
t.join()Partager des données entre processus
Entre les processus, utilisez plutôt multiprocessing.Queue. Elle sérialise les objets entre des espaces mémoire distincts.
import multiprocessing as mp
def producer(q):
for i in range(3):
q.put(i * i)
if __name__ == '__main__':
q = mp.Queue()
p = mp.Process(target=producer, args=(q,))
p.start()
p.join()
while not q.empty():
print('received', q.get())Éviter les interblocages
Un interblocage se produit lorsque des threads attendent indéfiniment les verrous les uns des autres. Évitez ce problème en acquérant toujours plusieurs verrous dans le même ordre, partout dans le programme.
import threading
lock_a = threading.Lock()
lock_b = threading.Lock()
def safe():
with lock_a:
with lock_b:
print('acquired in consistent order')
safe()Privilégier les files d'attente aux verrous
Lorsque c'est possible, privilégiez la transmission de messages avec des files d'attente plutôt qu'un état mutable partagé protégé par des verrous. Cette approche est plus facile à comprendre et entraîne beaucoup moins d'erreurs.
import queue
q = queue.Queue()
for word in ['safe', 'simple', 'clear']:
q.put(word)
while not q.empty():
print(q.get())Vérification rapide
Vérifiez votre compréhension du partage sûr des données.
Récapitulatif
Vous avez appris à partager des données en toute sécurité :
- Les conditions de concurrence corrompent l'état partagé qui n'est pas protégé.
LocketRLockprotègent les sections critiques.queue.Queueest sûre pour les threads ; utilisezmultiprocessing.Queueentre les processus.Eventpermet la signalisation entre les threads ; un ordre cohérent d'acquisition des verrous évite les interblocages.
Cours suivant : exécuter des programmes externes avec subprocess.
Questions Fréquemment Posées
La leçon « Partager les données en toute sécurité » est-elle gratuite ?
Oui — le texte complet de « Partager les données en toute sécurité » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Python Academy, passe à CoddyKit PRO. Le cours Python Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Partager les données en toute sécurité » ?
Utiliser des files et des verrous Tu pratiques Python Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Python Academy ?
Aucune expérience préalable n'est requise. Python Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Partager les données en toute sécurité » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Python Academy ?
Oui. Chaque leçon Python Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Threads et GIL
- ThreadPoolExecutor
- Les bases de multiprocessing
- Partager les données en toute sécurité