บทที่ 6: Concurrency — การทำงานพร้อมกัน
2 min readภาพรวม
นิยาม:
- Concurrency = เมื่อโค้ดตั้งแต่สองส่วนขึ้นไปทำงาน ราวกับว่า ทำงานพร้อมกัน (software mechanism)
- Parallelism = เมื่อมันทำงานพร้อมกัน จริง ๆ (hardware — multiple cores/CPUs)
Concurrency ไม่ใช่ทางเลือกอีกต่อไป — มันคือข้อบังคับสำหรับแอปพลิเคชันที่ต้องรับมือกับโลกจริงที่ทุกอย่างเป็น asynchronous
Topic 33: Breaking Temporal Coupling — ทำลาย coupling เชิงเวลา
Tip 56: Analyze Workflow to Improve Concurrency — วิเคราะห์ workflow เพื่อเพิ่ม concurrency
Temporal coupling คือการ coupling ในเชิงเวลา — method A ต้องเรียกก่อน method B เสมอ, รัน report ได้ทีละอัน, ต้องรอหน้าจอ redraw ก่อนถึงรับ click ได้
ใช้ Activity Diagrams ระบุสิ่งที่ทำพร้อมกันได้และสิ่งที่ต้องทำตามลำดับ — แล้วหาโอกาสในการทำกิจกรรมที่ใช้เวลานาน (เช่น query database, เข้าถึง external service, รอ user input) ไปพร้อมกับงานอื่น
โอกาสสำหรับ Parallelism: แบ่งงานใหญ่ออกเป็นชิ้นอิสระ — ประมวลผลแต่ละชิ้นแบบ parallel — รวมผลลัพธ์
Topic 34: Shared State Is Incorrect State — shared state คือ state ที่ผิด
Tip 57: Shared State Is Incorrect State
Tip 58: Random Failures Are Often Concurrency Issues
ปัญหา classic: server สองคนเห็น pie ชิ้นสุดท้ายในตู้ — ทั้งคู่รับออเดอร์ — ลูกค้าหนึ่งคนต้องผิดหวัง
ปัญหาไม่ได้อยู่ที่การเขียนข้อมูลแชร์กัน — แต่อยู่ที่การที่ไม่มีใครรับประกันได้ว่าภาพของ memory ที่ตัวเองเห็นนั้น consistent — การอ่านและอัปเดตค่าไม่ใช่ atomic operation
วิธีแก้ปัญหาแบบดั้งเดิม (และปัญหาของมัน):
- Semaphores/Mutexes: ทำงานได้ถ้า ทุกคน ทำตาม convention — ถ้าใครลืมใช้ semaphore ระบบก็พัง
- ทำให้ resource เป็น transactional: ย้าย logic การป้องกันไว้ที่ resource เอง — แต่ยังต้องจัดการ semaphore + exception handling อยู่ดี
- Multiple resource transactions: ซับซ้อนมากเมื่อต้องจัดการหลาย resource พร้อมกัน — ต้องคิดเผื่อการ "คืนของ" และ exception handling
"Doctor, it hurts when I do this." — "Then don't do that."
Topic 35: Actors and Processes — ตัวแสดงและกระบวนการ
Tip 59: Use Actors For Concurrency Without Shared State
Actor คืออะไร: virtual processor ที่มี state ส่วนตัวและ mailbox — เมื่อมีข้อความมาถึงและ actor ว่าง — มันจะประมวลผลข้อความ — สร้าง actor ใหม่, ส่งข้อความไป actor อื่น, และสร้าง state ใหม่
คุณสมบัติสำคัญ:
- ไม่มีใครควบคุมจากส่วนกลาง
- state ทั้งหมดอยู่ใน messages และ local state ของแต่ละ actor — ไม่มี shared state
- ข้อความเป็น one-way — ไม่มี concept ของการ reply โดยตรง
- ประมวลผลทีละหนึ่งข้อความจนเสร็จ
ข้อดี: ไม่ต้องเขียนโค้ดจัดการ concurrency — ไม่มี shared state — ทำงานได้เหมือนกันบน single processor, multiple cores, หรือ networked machines
Erlang/Elixir เป็นตัวอย่างที่ดี — มี lightweight processes, supervision trees (จัดการ failure), และ hot-code loading
Topic 36: Blackboards — กระดานดำ
Tip 60: Use Blackboards to Coordinate Workflow
ลองนึกถึงนักสืบที่ไขคดีฆาตกรรม — หัวหน้าสารวัตรตั้งกระดานดำเขียนคำถาม — นักสืบแต่ละคนเพิ่มข้อมูล, หลักฐาน, ข้อสันนิษฐาน — ไม่มีใครต้องรู้ว่าใครอยู่ — ทุกคนดู board และเพิ่มสิ่งที่ตัวเองรู้
คุณสมบัติของ blackboard:
- ผู้เข้าร่วม (detectives/agents/actors) ไม่จำเป็นต้องรู้จักกัน
- อาจมีความเชี่ยวชาญต่างกัน
- เข้า-ออกระบบได้ตลอดเวลา
- ไม่มีข้อจำกัดว่าต้องวางอะไรบน board
การประยุกต์ใช้กับซอฟต์แวร์: ระบบ mortgage/loan applications — กฎหมายซับซ้อน, ข้อมูลมาจากหลายแหล่งและมาถึงไม่พร้อมกัน, การมาถึงของข้อมูลใหม่อาจทำให้เกิดคำถามใหม่ — blackboard + rules engine จัดการได้อย่างสง่างาม
Messaging systems สมัยใหม่ (Kafka, NATS): ทำหน้าที่คล้าย blackboard — มี persistence (event log) และ pattern matching — ใช้เป็นทั้ง blackboard และ platform สำหรับ actors ได้