0Pricing
Python Academy · บทเรียน

การแบ่งปันข้อมูลอย่างปลอดภัย

ใช้คิวและล็อก

การแบ่งปันข้อมูลอย่างปลอดภัย เป็นบทเรียน Python Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Python Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

ปัญหาสภาวะแข่งขัน

เมื่อมีเธรดหลายตัวแก้ไขข้อมูลเดียวกัน การทำงานของเธรดอาจสอดแทรกกันและทำให้ผลลัพธ์เสียหายได้ สิ่งนี้เรียกว่าสภาวะแข่งขัน เราจำเป็นต้องใช้เครื่องมือประสานการทำงานเพื่อแบ่งปันข้อมูลอย่างปลอดภัย

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 แก้ปัญหา

threading.Lock ทำให้มั่นใจได้ว่ามีเธรดเพียงตัวเดียวเข้าสู่ส่วนวิกฤตได้ในแต่ละครั้ง ให้ยึดล็อกด้วยบล็อก with ที่ครอบการอัปเดตข้อมูลร่วมกัน

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 และ release

สามารถใช้ล็อกด้วยตนเองผ่าน acquire() และ release() ได้ แต่รูปแบบ with ปลอดภัยกว่า เพราะจะปล่อยล็อกแม้เกิดข้อผิดพลาด

import threading

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

คิวที่ปลอดภัยสำหรับเธรด

คลาส queue.Queue ปลอดภัยสำหรับเธรดอยู่แล้ว เธรดสามารถ put และ get ได้โดยไม่ต้องใช้ล็อกอย่างชัดเจน จึงเป็นวิธีที่แนะนำสำหรับส่งข้อมูล

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

ผู้ผลิตและผู้บริโภค

รูปแบบคลาสสิกคือ ผู้ผลิต put งานลงในคิว ส่วนผู้บริโภค get งานและประมวลผล คิวจะจัดการการล็อกทั้งหมดให้

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 และ task_done

q.join() จะบล็อกจนกว่าทุกรายการที่ถูก put จะมีการเรียก task_done() ที่ตรงกัน วิธีนี้ทำให้เธรดหลัก wait ให้งานทั้งหมดเสร็จสิ้นได้

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 สำหรับการเข้าซ้ำ

Lock ธรรมดาจะเกิดการชะงักงัน หากเธรดเดียวกันพยายามยึดล็อกสองครั้ง ส่วน threading.RLock หรือล็อกแบบเข้าซ้ำได้ อนุญาตให้ทำเช่นนั้นได้โดยนับจำนวนครั้งที่ยึดล็อก

import threading

rlock = threading.RLock()

def outer():
    with rlock:
        inner()

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

outer()

Event สำหรับส่งสัญญาณ

threading.Event ช่วยให้เธรดหนึ่งส่งสัญญาณไปยังเธรดอื่นได้ เธรดจะเรียก wait() จนกว่าอีกเธรดจะเรียก 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()

การแบ่งปันข้อมูลระหว่างกระบวนการ

ระหว่างกระบวนการ ให้ใช้ multiprocessing.Queue แทน คิวนี้จะแปลงอ็อบเจ็กต์เพื่อส่งระหว่างพื้นที่หน่วยความจำที่แยกจากกัน

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

การหลีกเลี่ยงภาวะชะงักงัน

ภาวะชะงักงันเกิดขึ้นเมื่อเธรดรอล็อกของกันและกันไปตลอดกาล ให้หลีกเลี่ยงโดยยึดล็อกหลายตัวตามลำดับเดียวกันในทุกที่เสมอ

import threading

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

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

safe()

เลือกใช้คิวแทนล็อก

เมื่อเป็นไปได้ ควรเลือกส่งข้อความด้วยคิวแทนการใช้สถานะที่เปลี่ยนแปลงร่วมกันซึ่งมีล็อกควบคุม วิธีนี้ทำความเข้าใจได้ง่ายกว่าและมีโอกาสเกิดข้อผิดพลาดน้อยกว่ามาก

import queue

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

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจของคุณเกี่ยวกับการแบ่งปันข้อมูลอย่างปลอดภัย

ทบทวน

คุณได้เรียนรู้วิธีแบ่งปันข้อมูลอย่างปลอดภัย:

  • สภาวะแข่งขันทำให้สถานะร่วมที่ไม่มีการป้องกันเสียหาย
  • Lock และ RLock ป้องกันส่วนวิกฤต
  • queue.Queue ปลอดภัยสำหรับเธรด ส่วนระหว่างกระบวนการให้ใช้ multiprocessing.Queue
  • Event ใช้ส่งสัญญาณระหว่างเธรด การใช้ลำดับล็อกที่สอดคล้องกันช่วยหลีกเลี่ยงภาวะชะงักงัน

หลักสูตรถัดไป: การเรียกใช้โปรแกรมภายนอกด้วยโมดูลสำหรับเรียกใช้กระบวนการ

คำถามที่พบบ่อย

บทเรียน “การแบ่งปันข้อมูลอย่างปลอดภัย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การแบ่งปันข้อมูลอย่างปลอดภัย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Python Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การแบ่งปันข้อมูลอย่างปลอดภัย”

ใช้คิวและล็อก คุณปฏิบัติ Python Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Python Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Python Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การแบ่งปันข้อมูลอย่างปลอดภัย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Python Academy นี้ได้ไหม

ได้ บทเรียน Python Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เธรดและ GIL
  2. ThreadPoolExecutor
  3. พื้นฐาน multiprocessing
  4. การแบ่งปันข้อมูลอย่างปลอดภัย
← กลับไปที่ Python Academy