การแบ่งปันข้อมูลอย่างปลอดภัย
ใช้คิวและล็อก
การแบ่งปันข้อมูลอย่างปลอดภัย เป็นบทเรียน 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.QueueEventใช้ส่งสัญญาณระหว่างเธรด การใช้ลำดับล็อกที่สอดคล้องกันช่วยหลีกเลี่ยงภาวะชะงักงัน
หลักสูตรถัดไป: การเรียกใช้โปรแกรมภายนอกด้วยโมดูลสำหรับเรียกใช้กระบวนการ
คำถามที่พบบ่อย
บทเรียน “การแบ่งปันข้อมูลอย่างปลอดภัย” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแบ่งปันข้อมูลอย่างปลอดภัย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เธรดและ GIL
- ThreadPoolExecutor
- พื้นฐาน multiprocessing
- การแบ่งปันข้อมูลอย่างปลอดภัย