Python Academy · Pelajaran

Berkongsi Data dengan Selamat

Gunakan baris gilir dan kunci

Pelajaran 4 daripada 413 langkah

Berkongsi Data dengan Selamat ialah pelajaran Python Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Python Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Python Academy merangkumi sejumlah 4 pelajaran.

Masalah Keadaan Perlumbaan

Apabila beberapa urutan mengubah suai data yang sama, operasi mereka boleh berselang-seli lalu merosakkan hasil. Ini ialah keadaan perlumbaan. Kita memerlukan alat penyegerakan untuk berkongsi data dengan selamat.

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 sebagai Penyelamat

threading.Lock memastikan hanya satu urutan memasuki bahagian kritikal pada satu-satu masa. Dapatkan kunci itu dengan blok with yang mengelilingi kemas kini dikongsi.

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

Kunci boleh digunakan secara manual dengan acquire() dan release(), tetapi bentuk with lebih selamat kerana kunci akan dilepaskan walaupun ralat berlaku.

import threading

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

Baris Gilir Selamat untuk Urutan

Kelas queue.Queue sudah selamat untuk urutan. Urutan boleh melakukan put dan get tanpa kunci eksplisit, menjadikannya cara pilihan untuk menghantar data.

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 dan Consumer

Corak klasik: pengeluar memasukkan kerja ke dalam baris gilir dengan put, manakala pengguna mendapatkannya dengan get lalu memprosesnya. Baris gilir mengendalikan semua penguncian.

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

q.join() menyekat sehingga setiap item yang telah put menerima padanan task_done(). Dengan ini, urutan utama boleh menunggu sehingga semua kerja selesai.

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 untuk Kemasukan Semula

Lock biasa mengalami kebuntuan jika urutan yang sama cuba mendapatkannya dua kali. threading.RLock (kunci boleh masuk semula) membenarkannya dengan mengira bilangan pemerolehan.

import threading

rlock = threading.RLock()

def outer():
    with rlock:
        inner()

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

outer()

Event untuk Memberi Isyarat

threading.Event membolehkan satu urutan memberi isyarat kepada urutan lain. Urutan memanggil wait() sehingga urutan lain memanggil 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()

Berkongsi Merentas Proses

Merentas proses, gunakan multiprocessing.Queue sebagai ganti. Ia menyiri objek antara ruang memori yang berasingan.

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

Mengelakkan Kebuntuan

Kebuntuan berlaku apabila urutan menunggu kunci satu sama lain tanpa henti. Elakkannya dengan sentiasa mendapatkan beberapa kunci dalam susunan yang sama di semua tempat.

import threading

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

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

safe()

Utamakan Baris Gilir Berbanding Kunci

Jika boleh, utamakan penghantaran mesej melalui baris gilir berbanding keadaan boleh ubah dikongsi yang dilindungi oleh kunci. Cara ini lebih mudah difahami dan jauh kurang terdedah kepada pepijat.

import queue

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

Semakan Pantas

Uji pemahaman anda tentang perkongsian data yang selamat.

Ringkasan

Anda telah mempelajari cara berkongsi data dengan selamat:

  • Keadaan perlumbaan merosakkan keadaan dikongsi yang tidak dilindungi.
  • Lock dan RLock melindungi bahagian kritikal.
  • queue.Queue selamat untuk urutan; gunakan multiprocessing.Queue merentas proses.
  • Event memberi isyarat antara urutan; susunan kunci yang konsisten mengelakkan kebuntuan.

Kursus seterusnya: menjalankan program luaran dengan subprocess.

Percuma untuk bermula

Pelajari Python dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
76
Pelajaran
320

Soalan Lazim

Adakah pelajaran “Berkongsi Data dengan Selamat” percuma?

Ya — teks penuh “Berkongsi Data dengan Selamat” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Python Academy, tingkat taraf kepada CoddyKit PRO. Kursus Python Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Berkongsi Data dengan Selamat”?

Gunakan baris gilir dan kunci Anda berlatih Python Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Python Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Python Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.

Berapa lamakah pelajaran “Berkongsi Data dengan Selamat” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Python Academy ini?

Ya. Setiap pelajaran Python Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Thread dan GIL
  2. ThreadPoolExecutor
  3. Asas multiprocessing
  4. Berkongsi Data dengan Selamat
← Kembali ke Python Academy