Trygg deling av data
Bruk køer og låser
Trygg deling av data er en gratis leksjon i Python Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Python Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Python Academy inneholder totalt 4 leksjoner.
Problemet med kappløpstilstander
Når flere tråder endrer de samme dataene, kan operasjonene deres flettes inn i hverandre og ødelegge resultatet. Dette kalles en kappløpstilstand. Vi trenger synkroniseringsverktøy for å dele data på en trygg måte.
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)Låsen til unnsetning
En threading.Lock sørger for at bare én tråd om gangen går inn i en kritisk seksjon. Skaff låsen med en with-blokk rundt oppdateringen av de delte dataene.
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 og release
En lås kan brukes manuelt med acquire() og release(), men with-formen er tryggere fordi den frigir låsen selv om det oppstår en feil.
import threading
lock = threading.Lock()
lock.acquire()
try:
print('inside critical section')
finally:
lock.release()
print('released')Trådsikre køer
Klassen queue.Queue er allerede trådsikker. Tråder kan bruke put og get uten eksplisitte låser, noe som gjør den til den foretrukne måten å overføre data på.
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())Produsent og konsument
Det klassiske mønsteret er at produsenter legger arbeid i en kø med put, mens konsumenter henter og behandler det med get. Køen håndterer all låsing.
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 og task_done
q.join() blokkerer til hvert element som er lagt inn med put, har fått et tilsvarende kall til task_done(). Dermed kan hovedtråden vente til alt arbeidet er ferdig.
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 for reentrant bruk
En vanlig Lock fører til deadlock hvis den samme tråden prøver å skaffe den to ganger. En threading.RLock (reentrant lås) tillater dette ved å telle antall ganger låsen er skaffet.
import threading
rlock = threading.RLock()
def outer():
with rlock:
inner()
def inner():
with rlock:
print('re-entered safely')
outer()Event for signalering
En threading.Event lar én tråd signalisere til andre. Tråder kaller wait() til en annen tråd kaller 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()Deling mellom prosesser
Mellom prosesser bruker du i stedet multiprocessing.Queue. Den serialiserer objekter mellom separate minneområder.
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())Unngå deadlock
Deadlock oppstår når tråder venter på hverandres låser for alltid. Unngå dette ved alltid å skaffe flere låser i samme rekkefølge overalt.
import threading
lock_a = threading.Lock()
lock_b = threading.Lock()
def safe():
with lock_a:
with lock_b:
print('acquired in consistent order')
safe()Foretrekk køer fremfor låser
Når det er mulig, bør du foretrekke meldingsutveksling med køer fremfor delt, muterbar tilstand som beskyttes av låser. Det er enklere å forstå og gir langt færre feil.
import queue
q = queue.Queue()
for word in ['safe', 'simple', 'clear']:
q.put(word)
while not q.empty():
print(q.get())Kort test
Test forståelsen din av trygg datadeling.
Oppsummering
Du har lært å dele data på en trygg måte:
- Kappløpstilstander kan ødelegge delt tilstand som ikke er beskyttet.
LockogRLockbeskytter kritiske seksjoner.queue.Queueer trådsikker; brukmultiprocessing.Queuemellom prosesser.Eventsignaliserer mellom tråder, og en konsekvent rekkefølge for låsing unngår deadlock.
Neste kurs: kjøre eksterne programmer med subprocess.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 76
- Leksjoner
- 320
Ofte stilte spørsmål
Er leksjonen «Trygg deling av data» gratis?
Ja – hele teksten i «Trygg deling av data» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Python Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Python Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Trygg deling av data»?
Bruk køer og låser Du øver på Python Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Python Academy?
Ingen tidligere erfaring er nødvendig. Python Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Trygg deling av data»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Python Academy-leksjonen?
Ja. Alle Python Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Tråder og GIL
- ThreadPoolExecutor
- Grunnleggende om multiprocessing
- Trygg deling av data