Critical-Section Problem อ. รวินทร์ ไชยสิทธิพร
Critical Section คืออะไร ขอบเขตวิกฤต ส่วนของโค๊ดที่มีการใช้ทรัพยากรบางอย่างร่วมกัน ระหว่างโปรเซส 2 ตัวขึ้นไป ส่วนใหญ่จะเป็น “ตัวแปร” หรือ “ข้อมูล” อาจเกิดปัญหาในเรื่องความถูกต้องของข้อมูล
ตัวอย่าง ปัญหาอยู่ที่ใด ? สมมติว่ามีโปรเซส 2 ตัว ทำงานในเวลาใกล้เคียงกันมาก โปรเซสที่ 1 : counter = counter + 1 งานใน CPU R1 = counter R1 = R1 + 1 counter = R1 (R1 = register) -โปรเซสที่ 2 : counter = counter - 1 R2 = counter R2 = R2 - 1 counter = R2 ปัญหาอยู่ที่ใด ?
ลองดูในแต่ละจังหวะเวลา เวลาที่ 0 : R1 = counter (R1 = 5) เวลาที่ 1 : R1 = R1 + 1 (R1 = 6) เวลาที่ 2 : R2 = counter (R2 = 5) เวลาที่ 3 : R2 = R2 -1 (R2 = 4) เวลาที่ 4 : counter = R1 (counter = 6) เวลาที่ 5 : counter = R2 (counter = 4) ลองดูซิว่า Error ตรงไหน ? สถานการณ์นี้เรียกว่า “การแข่งขัน” (Race Condition)
การทดลอง ให้เขียนโปรแกรมด้วยภาษา Java เมื่อเขียนเสร็จเซฟไฟล์ให้ชื่อว่า CriticalSecTest.java มีต่อ
รันโปรแกรม ก่อนการรันก็คอมไพล์ก่อน แล้วรันด้วยคำสั่ง java CriticalSecTest ลองรันหลายๆครั้งแล้วสังเกตดูว่า ผลลัพธ์ในแต่ละครั้งเป็นอย่างไร บันทึกผลการทดลอง สรุปผลการทดลองส่งอาจารย์
การแก้ปัญหา Critical Section กำหนดข้อกำหนดของการแก้ปัญหา 1. ต้องมีการกีดกันต่อกัน (Mutual Exclusion) 2. ต้องมีการก้าวหน้า (Progress) 3. ต้องมีการรอคอยที่จำกัด (Bounded Waiting)
รูปแบบของ Critical Section repeat Entry Section Critical Section Exit Section Remainder section until false (ใช้กับทุกๆ Solution)
Solution ที่1 : การแก้ปัญหา 2 โปรเซส ใน Solution นี้จะใช้กับ Race Condition ระหว่างโปรเซส 2 ตัว มีรูปแบบดังนี้ ** โค๊ดของ Pi repeat while turn ≠ i do no-op; กำหนดให้มีโปรเซส Pi และ Pj turn คือตัวแปร Critical Section turn := j Remainder section until false
วิเคราะห์ข้อดีข้อเสีย ให้น.ศ. ลองวิเคราะห์ข้อดี – ข้อเสียของ Solution ในหน้าที่แล้ว ใครตอบได้เป็นที่ถูกใจอาจารย์ 3 คนแรกจะได้คะแนนฟรี ทำการทดลอง ให้เปิด EditPlus เพื่อเขียนโปรแกรมด้วย Java
โปรแกรม มีต่อ
while flag[j] do no-op; Solution ที่ 2 ** โค๊ดของ Pi repeat flag[i] := true; while flag[j] do no-op; flag[ ] คืออาเรย์ของ Boolean Critical Section flag[i] := false; Remainder section until false
โปรแกรม มีต่อ
การประสานงานระหว่างหลายโปรเซส ที่ผ่านมาเป็นอัลกอริธึมของการ Synchronize ระหว่าง 2 โปรเซสเท่านั้น แต่หากเป็นการประสานงานระหว่างหลายโปรเซสล่ะ อัลกอริธึมแบบร้านเบเกอรี หลักการ แต่ละคนที่ต้องการจะเข้าไปซื้อเบเกอรี จะต้องมีบัตรคิว ลูกค้าที่ได้บัตรหมายเลขน้อยกว่า จะได้รับบริการก่อน หากว่าลูกค้าเข้าร้านพร้อมๆกัน และได้บัตรคิวหมายเลขเดียวกัน ให้เรียงลำดับตามชื่อของลูกค้า
อัลกอริธึม Critical Section กำหนดตัวแปรดังนี้ choosing : ARRAY[0...n-1] OF BOOLEAN number : ARRAY[0..n-1] OF INTEGER ค่าเริ่มต้นของ choosing ทั้งหมดเป็น FALSE และทั้งหมดของ number เป็น 0 กำหนดให้ (a,b) < (c,d) ถ้า a < c หรือ (a = c และ b < d) max(a0, …, an-1) เป็นฟังก์ชั่นที่หาค่ามากที่สุดของ a0 ถึง an-1 REPEAT choosing[i] := TRUE; number[i] := max(number[0],number[1],…,number[n-1]) + 1; choosing[i] := FALSE FOR j := 0 to n-1 DO BEGIN WHILE choosing[j] DO no-op; WHILE number[j] <> 0 AND (number[j],j) < (number[i],i); DO no-op; END Critical Section number[i] := 0; UNTIL FALSE;
การประสานงานด้วยฮาร์ดแวร์ จากตัวอย่างที่กล่าวมาในสไลด์แผ่นที่ 3 นั้น เราอาจป้องกันได้ด้วยการ Disable การทำงานของ Interrupt เมื่ออยู่ในช่วงที่ใช้ตัวแปรร่วมกัน P1 P2 CPU DON’T INTERRUPT COUNTER เราเรียกคำสั่งที่ห้ามการ Interrupt นี้ว่า คำสั่งแบบ Atomic
ตัวอย่างของ Atomic Instruction คำสั่ง Test and Set กำหนดฟังก์ชั่น FUNCTION Test-and-Set(VAR target:BOOLEAN) : BOOLEAN BEGIN Test-and-Set := target; target := TRUE; END; ***การนำไปใช้เรื่อง Mutual Exclusion** กำหนดตัวแปร VAR lock : BOOLEAN = FALSE REPEAT WHILE Test-and-Set(lock) DO no-op; Critical Section Lock := FALSE; UNTIL FALSE;
Semaphore กำหนดให้คำสั่ง ดังนี้เป็น Atomic Instruction S = integer WAIT(S) WHILE S <= 0 DO no-op; S : S-1; SIGNAL(S) S := S+1; S = integer S เรียกว่าเป็น Semaphore
การนำ Semaphore ไปใช้งาน กำหนดให้ mutex เป็น Semaphore ดังนี้ VAR mutex : SEMAPHORE = 1; repeat WAIT(mutex); Critical Section SIGNAL(mutex); Remainder section until false
เขียนโปรแกรม มีต่อ
ปัญหานักปราชญ์ 5 คน มีนักปราญ์ 5 คน นั่งล้อมรอบโต๊ะกินข้าว จะคุยกันทั้งวัน เมื่อหิวก็จะกินข้าว โดยการใช้ตะเกียบ มีข้อจำกัดในการใช้ตะเกียบ หากใครใช้ คนนั่งข้างๆจะใช้ไม่ได้
ภาพอธิบาย นักปราชญ์ ตะเกียบ อาหาร ปัญหาคืออะไร แก้ได้อย่างไร
การแก้ปัญหา ให้นักปราชญ์นั่งโต๊ะได้มาเกิน 4 คน ให้นักปราชญ์หยิบตะเกียบเมื่อตะเกียบทั้งคู่ว่างเท่านั้น ห้ามหยิบทีละข้าง (ดังนั้น จะต้องทำงานในเขตวิกฤต) นักปราชญ์คนที่นั่งเลขคี่หยิบตะเกียบข้างซ้ายก่อนขวา ส่วนนักปราชญ์คนที่นั่งเลขคู่หยิบตะเกียบข้างขวาก่อนข้างซ้าย
ใช้ Semaphore REPEAT WAIT(chopstick[i]); WAIT(chopstick[i+1 MOD 5]); … VAR chopstick : ARRAY[0..4] OF SEMAPHORE ***โค๊ดของนักปราชญ์คนที่ i REPEAT WAIT(chopstick[i]); WAIT(chopstick[i+1 MOD 5]); … กินข้าวได้ …. SIGNAL(chopstick[i]); SIGNAL(chopstick[i+1 MOD 5]); คิด UNTIL FALSE; Chopstick[0] P0 อาหาร Chopstick[1] P1 Chopstick[2]
สรุป จบบท การประสานงานระหว่างโปรเซสเป็นสิ่งที่สำคัญ ต้องมี ความก้าวหน้า การไม่อยู่ใน Critical Section พร้อมกัน การรอคอยที่จำกัด อัลกอริธึมเป็นการใช้ซอฟท์แวร์จัดการ แต่อาจต้องใช้ฮาร์ดแวร์ร่วมด้วย การบ้าน ให้นศ.สรุปและอธิบายข้อดี-ข้อเสียของอัลกอริธึมในการประสานงานของโปรเซสแต่ละตัว ทุกตัว และแสดงการเปรียบเทียบให้เห็นด้วย จบบท