Python Academy · Oppitunti

Tietojen turvallinen jakaminen

Käytä jonoja ja lukkoja

Oppitunti 4/413 vaihetta

Tietojen turvallinen jakaminen on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Python Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Python Academy-kurssilla on yhteensä 4 oppituntia.

Kilpailutilanteen ongelma

Kun useat säikeet muokkaavat samoja tietoja, niiden operaatiot voivat lomittua ja turmella tuloksen. Tätä kutsutaan kilpailutilanteeksi. Tarvitsemme synkronointityökaluja tietojen turvalliseen jakamiseen.

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)

Lukko apuun

threading.Lock varmistaa, että vain yksi säie kerrallaan siirtyy kriittiseen osioon. Hankkikaa lukko käyttämällä jaettua päivitystä ympäröivää with-lohkoa.

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 ja release

Lukkoa voi käyttää manuaalisesti acquire()- ja release()-metodeilla, mutta with-muoto on turvallisempi, koska se vapauttaa lukon myös virheen sattuessa.

import threading

lock = threading.Lock()
lock.acquire()
try:
    print('inside critical section')
finally:
    lock.release()
print('released')

Säieturvalliset jonot

queue.Queue-luokka on valmiiksi säieturvallinen. Säikeet voivat kutsua put- ja get-metodeja ilman erillisiä lukkoja, joten se on suositeltu tapa välittää tietoja.

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())

Tuottaja ja kuluttaja

Klassinen malli: tuottajat sijoittavat työn jonoon put-kutsulla, ja kuluttajat hakevat ja käsittelevät sen get-kutsulla. Jono huolehtii kaikesta lukitsemisesta.

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 ja task_done

q.join() estää suorituksen, kunnes jokaiselle jonoon put-kutsulla lisätylle alkiolle on kutsuttu vastaavaa task_done()-metodia. Näin pääsäie voi odottaa kaiken työn valmistumista.

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 uudelleenentranssia varten

Tavallinen Lock aiheuttaa lukkiutumisen, jos sama säie yrittää hankkia sen kahdesti. threading.RLock eli uudelleenentranssi lukko sallii tämän ja pitää kirjaa hankintakerroista.

import threading

rlock = threading.RLock()

def outer():
    with rlock:
        inner()

def inner():
    with rlock:
        print('re-entered safely')

outer()

Event ilmoitusten välittämiseen

threading.Event mahdollistaa yhden säikeen ilmoituksen muille säikeille. Säikeet kutsuvat wait()-metodia, kunnes jokin toinen säie kutsuu set()-metodia.

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()

Jakaminen prosessien välillä

Käyttäkää prosessien välillä sen sijaan multiprocessing.Queue-jonoa. Se sarjallistaa oliot erillisten muistiavaruuksien välillä.

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())

Lukkiutumisen välttäminen

Lukkiutuminen syntyy, kun säikeet odottavat toistensa lukkoja loputtomasti. Välttäkää sitä hankkimalla useat lukot aina samassa järjestyksessä kaikkialla.

import threading

lock_a = threading.Lock()
lock_b = threading.Lock()

def safe():
    with lock_a:
        with lock_b:
            print('acquired in consistent order')

safe()

Suosikaa jonoja lukkojen sijaan

Kun mahdollista, suosikaa viestinvälitystä jonojen avulla jaettuun, lukkojen suojaamaan muokattavaan tilaan verrattuna. Sen toimintaa on helpompi ymmärtää, ja se aiheuttaa paljon vähemmän virheitä.

import queue

q = queue.Queue()
for word in ['safe', 'simple', 'clear']:
    q.put(word)
while not q.empty():
    print(q.get())

Pikatarkistus

Testatkaa, miten hyvin hallitsette tietojen turvallisen jakamisen.

Kertaus

Opitte jakamaan tietoja turvallisesti:

  • Kilpailutilanteet turmelevat suojaamattoman jaetun tilan.
  • Lock ja RLock suojaavat kriittisiä osioita.
  • queue.Queue on säieturvallinen; käyttäkää multiprocessing.Queue-jonoa prosessien välillä.
  • Event välittää ilmoituksia säikeiden välillä, ja yhdenmukainen lukkojen hankintajärjestys estää lukkiutumisen.

Seuraava kurssi: ulkoisten ohjelmien suorittaminen subprocess-moduulilla.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
76
Oppitunnit
320

Usein kysytyt kysymykset

Onko oppitunti ”Tietojen turvallinen jakaminen” ilmainen?

Kyllä – oppitunnin ”Tietojen turvallinen jakaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Python Academy-kurssin, päivitä CoddyKit PROhon. Python Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Tietojen turvallinen jakaminen”?

Käytä jonoja ja lukkoja Harjoittelet Python Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Python Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Python Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Tietojen turvallinen jakaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Python Academy-oppitunnilla?

Kyllä. Jokainen Python Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Säikeet ja GIL
  2. ThreadPoolExecutor
  3. multiprocessing-perusteet
  4. Tietojen turvallinen jakaminen
← Takaisin: Python Academy