1 / 54

Operating System

Operating System. บทที่ 6 การประสานงานของกระบวนการ (PROCESS SYNCHRONIZATION). ความเป็นมา (Background).

kassia
Download Presentation

Operating System

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Operating System บทที่ 6 การประสานงานของกระบวนการ (PROCESS SYNCHRONIZATION)

  2. ความเป็นมา (Background) • ในบทที่ 4 ในเรื่องของการแก้ปัญหาหน่วยความร่วม ซึ่งมีที่พักข้อมูลแบบมีขอบเขต (bounded-buffer) ซึ่งเราพูดไปแล้ว จะเห็นว่าโปรแกรมดังกล่าวสามารถเก็บข้อมูลในที่พักได้มากที่สุด n – 1 ตัวเท่านั้น ถ้าเราปรับปรุงอัลกอริทึมโดยเพิ่มตัวแปร count ซึ่งเป็นตัวแปรชนิดตัวเลข (integer) เริ่มจาก 0 count จะถูกเพิ่มค่าทุกครั้งที่เราเพิ่มข้อมูลใหม่เข้าไปในที่พักข้อมูล และลดครั้งทุกครั้งที่นำข้อมูลออกจากที่พักข้อมูล

  3. โปรแกรมผู้ผลิตจะกลายเป็นดังนี้โปรแกรมผู้ผลิตจะกลายเป็นดังนี้ • while (true) { • while (count == BUFFER_SIZE) • ; //do-nothing • buffer[in] = nextp; • in = (in + 1) % BUFFER_SIZE; • //add an item to the buffer • count++; • }

  4. โปรแกรมผู้ใช้ กลายเป็นดังนี้ • while (true) { • while (count == 0) • ; //do-nothing • nextc = buffer[out]; • out = (out + 1) % BUFFER_SIZE; • // remove an item from the buffer • count--; • }

  5. ถึงแม้ว่าโปรแกรมข้างต้นจะดูถูกต้อง แต่อาจมีการผิดพลาดได้ • ในสภาวะที่มีการทำงานขนานกัน (concurrent) • สมมติว่าขณะนี้ counter = 5 • ผู้ผลิตกำลังจะทำงานในประโยค counter := counter + 1; และ • ผู้ใช้กำลังจะทำงานในประโยค counter := counter – 1; ในเวลาเดียวกัน • ผลก็คือ counter อาจจะกลายเป็น 4, 5 หรือ 6 ก็ได้ โดยค่าที่ถูกต้องก็คือ 5 (ถ้าทำงานแบบตามลำดับ)

  6. ทำไมจึงเป็นเช่นนี้ • ดูประโยค counter := counter + 1; ในความเป็นจริงในภาษาเครื่องแยกการทำงานเป็น 3 ขั้นตอน ดังต่อไปนี้คือ • register1 := counter; • register1 := register1 + 1; • counter := register1;

  7. ในทำนองเดียวกัน • ประโยค counter := counter – 1; แยกได้เป็น • register2 := counter; • register2 := register2 - 1; • counter := register2;

  8. เมื่อมีการขัดจังหวะการทำงานเมื่อมีการขัดจังหวะการทำงาน • การทำงานแบบขนาน (concurrent) ของประโยค counter := counter + 1; และ counter := counter - 1; ก็คือ การทำงานในระดับเครื่อง แยกเป็น 6 คำสั่งข้างต้น เรียงลำดับกัน (อาจมีการสลับกันระหว่างคำสั่ง 2 กระบวนการ) การทำงานจริงอาจมีลำดับดังนี้

  9. T0 : producer execute register1 := counter [register1 = 5] • T1 : producer execute register1 := register1 + 1 [register1 = 6] • T2 : consumer execute register2 := counter [register2 = 5] • T3 : consumer execute register2 := register1 - 1 [register1 = 4] • T4 : producer execute counter := register1 [counter = 6] • T5 : consumer execute counter := register2 [counter = 4]

  10. จะเห็นได้ว่า ผลลัพธ์สุดท้าย counter = 4 ซึ่งไม่ถูกต้อง (ที่จริงควรเป็น 5) ถ้า เวลา T4 กับ T5 กลับกัน ผลลัพธ์ก็จะกลายเป็น counter = 6 ซึ่งก็ไม่ถูกต้องเช่นกัน • ที่เป็นเช่นนี้เพราะกระบวนการ 2 กระบวนการ อ่านและเขียนข้อมูลตัวเดียวกัน (คือ counter) ในเวลาขนานกัน สถานการณ์เช่นนี้ซึ่งหมายถึงกระบวนการหลาย ๆ กระบวนการเข้าถึง (access) และจัดการ (manipulate) ข้อมูลเดียวกันในเวลาขนานกัน แล้วผลลัพธ์ของการทำงานขึ้นอยู่กับคำสั่งที่กำลังเข้าถึงข้อมูลอยู่ ถูกเรียกว่า เงื่อนไขแข่งขัน (race condition)

  11. ปัญหาเขตวิกฤต (The Critical-Section Problem) • เมื่อกระบวนการหนึ่งกำลังทำงานในเขตวิกฤต ห้ามมีกระบวนการอื่นเข้ามาทำงานในเขตวิกฤตนั้น ดังนั้นการที่กระบวนการทำงานในเขตวิกฤต คือ การห้ามอยู่พร้อมกัน (mutually exclusive) • เขตที่ใช้จริง ๆ มี 3 เขต คือ • ช่วงร้องขอเข้าเรียกว่า entry section • ถ้าอยู่ในเขตวิกฤตแล้วต้องการออก เรียกว่า exit section • ช่วงหลังเขตวิกฤต เรียกว่า remainder section

  12. วิธีแก้ปัญหาเขตวิกฤตต้องแก้ 3 ข้อ ดังนี้ • การห้ามอยู่พร้อมกัน (Mutual Exclusion)ถ้ากระบวนการ P1 ทำงานอยู่ในเขตวิกฤต ห้ามกระบวนการอื่นทำงานในเขตนั้น • ความก้าวหน้า (Progress)ถ้ายังไม่มีกระบวนการใดทำงานในเขตวิกฤต และมีบางกระบวนการต้องการเข้าไปในเขตนั้น กระบวนการเหล่านั้นก็จะถูกนำมาตัดสินว่าใครจะได้เข้าไปในเขตวิกฤตเป็นลำดับถัดไป การคัดเลือกนี้ต้องชัดเจน เลื่อนสลับที่กันไม่ได้

  13. วิธีแก้ปัญหาเขตวิกฤตต้องแก้ 3 ข้อ ดังนี้ • การรอคอยอย่างมีขอบเขต (Bounded Waiting)ต้องมีขอบเขตของเวลาให้กระบวนการอื่นได้เข้าไปในเขตวิกฤตของตนเอง หลังจากกระบวนการได้ร้องขอเข้าเขตวิกฤต และก่อนหน้านั้นการร้องขอดังกล่าวต้องได้รับอนุญาตก่อนแล้ว • repeat • entry section • critical section • exit section • remainder section • until false;

  14. วิธีแก้ปัญหา 2 กระบวนการ(Two-Process Solution) • ในหัวข้อนี้มุ่งประเด็นไปที่ในช่วงเวลาหนึ่งมีกระบวนการแค่ 2 กระบวนการเท่านั้น คือ P0และ P1 • เพื่อความสะดวก เราใช้ Piและ Pjซึ่ง j = 1 – i

  15. Algorithm 1 • ขั้นแรกให้ทั้ง 2 กระบวนการร่วมกันใช้ตัวแปร turn ซึ่งเริ่มจาก 0 (หรือ 1) ถ้า turn = i กระบวนการ Piจะได้ทำงานในเขตวิกฤตของมัน โครงสร้างของ Piแสดงได้ดังนี้ • do { • while (turn != i) ; //do nothing • critical section • turn = j; • remainder section • } while (true);

  16. Algorithm 1 • นี้สามารถประกันได้ว่า จะมีเพียงกระบวนการเดียวเท่านั้น ในเขตวิกฤต แต่ไม่ผ่านคุณสมบัติ ความก้าวหน้า (Progress) เพราะกระบวนการทั้งสอง ต้องสลับกันเข้าใช้เขตวิกฤต คนละครั้งเป็นวงกลม เช่น ถ้า turn = 0 และ P1พร้อมที่จะเข้าเขตวิกฤต ก็จะไม่สามารถเข้าได้ แม้ว่า P0จะอยู่หลังเขตวิกฤต (remainder section) ก็ตาม

  17. Algorithm 2 • ปัญหาของ Algorithm 1 คือ ไม่มีการจัดเก็บสถานะของแต่ละกระบวนการไว้ มีเพียงตัวแปรเก็บค่า ว่าขณะนี้เป็นคราวของกระบวนการใด เราจึงอาจใช้ flag แทน turn ดังนี้ • ซึ่ง boolean flag[2]; • ให้ flag[0] := false; • flag[1] := false; เมื่อเริ่มต้น • เมื่อ Piต้องการจะเข้าเขตวิกฤต flag[i] = true พิจารณารูปถัดไป

  18. Algorithm 2 • do { • flag[i] = true; • while flag[j] ; //do nothing • critical section • flag[i] = false; • remainder section • } while (true);

  19. Algorithm 2 • ในขั้นตอน algorithm นี้ Piให้ flag[i] = true เพื่อที่แสดงว่า ต้องการจะเข้าเขตวิกฤต แล้วตรวจดูว่า Pjไม่ได้ต้องการจะเข้าเขตวิกฤตด้วย โดยดู flag[j] ถ้า Pjต้องการเข้าเขตวิกฤต (flag[j] = true) Piก็จะรอ (ทำคำสั่ง do nothing) จนกระทั่ง Pjออกจากเขตวิกฤต แล้วเปลี่ยน flag[j] = false Piจึงจะเข้าเขตวิกฤตได้ • วิธีนี้ ผ่านคุณสมบัติ การห้ามอยู่พร้อมกัน (mutually exclusion) แต่ไม่ผ่านคุณสมบัติ ความก้าวหน้า (Progress) ดังตัวอย่างเช่น • ณ เวลา T0: P0ทำคำสั่ง flag[0] = true • ณ เวลา T1: P1ทำคำสั่ง flag[1] = true • ถ้าเป็นเช่นนี้แล้วทั้ง P0และ P1จะติดอยู่ในวงจรรอบของ while ตลอดไป

  20. Algorithm 3 • โดยการรวมแนวคิดของ Algorithm 1 และ 2 เข้าด้วยกัน จะได้วิธีที่สมบูรณ์แบบสามารถผ่านคุณสมบัติทั้ง 3 ประการในปัญหาเขตวิกฤตได้ โดยกำหนดให้ ตัวแปรร่วมเป็นดังนี้ • boolean flag[2]; • int turn; • เริ่มต้น flag[0] = flag[1] = false และ turn อาจเป็น 0 หรือ 1 และโปรแกรมสำหรับกระบวนการ Piเป็น

  21. Algorithm 3 • do { • flag[i] = true; //กระบวนการแรกกำลังจะได้เข้าเขตวิกฤต • turn = j; //ให้ counter ของอีกกระบวนการหนึ่งเตรียมตัวเข้า CS เป็นลำดับถัดไป • while (flag[j] && turn == j) • ; do nothing //ถ้ามีกระบวนการใดอยู่ใน CS กระบวนการหลังต้องรอก่อน • critical section • flag[i] = false; //กระบวนการแรกออกมาแล้วต้อง set ตัวเองเป็น false • remainder section • } while (true);

  22. Algorithm 3 • เมื่อกระบวนการ Piต้องการเข้าเขตวิกฤต flag[i] = true และให้ turn เป็นของอีกกระบวนการหนึ่ง คือ j (turn=j) ถ้าทั้งสองกระบวนการต้องการเข้าเขตวิกฤตในเวลาเดียวกัน ค่า turn จะถูกกำหนดเป็น i และ j ในเวลาใกล้เคียงกัน turn จะกลายเป็นค่าสุดท้าย (i หรือ j) ซึ่งจะอนุญาตให้เพียงกระบวนการเดียวเข้าเขตวิกฤต • เราจะต้องพิสูจน์ว่า ขั้นตอน algorithm 3 นี้สามารถผ่านคุณสมบัติทั้ง 3 ประการ คือ • การห้ามอยู่พร้อมกัน (Mutually Exclusion) • ความก้าวหน้า (Progress) • การรอคอยอย่างมีขอบเขต (Bounded Waiting)

  23. Algorithm 3 • จะสังเกตเห็นว่า Piเข้าเขตวิกฤตได้ก็ต่อเมื่อ flag[j] = false หรือ turn = 1 และถ้ากระบวนการทั้งสอง สามารถอยู่ในเขตวิกฤตได้พร้อมกัน แล้ว flag[0] = flag[1] = true จากข้อสังเกต 2 ข้อที่กล่าวมานี้ สรุปได้ว่า P0และ P1ไม่สามารถผ่านประโยค while ในขณะเดียวกันได้ เพราะค่าของ turn มีได้เพียงค่าเดียวเท่านั้น (0 หรือ 1) ในขณะหนึ่ง ๆ ดังนั้นจะมีเพียงกระบวนการเดียวเท่านั้น (สมมติให้เป็น Pi) ที่ผ่านประโยค while ได้ ขณะที่ Pjยังคงติดใน while เพราะ turn = j และ flag[j] = true และจะติดอยู่ตราบเท่าที่ Piยังคงอยู่ในเขตวิกฤต สรุปได้ว่าวิธีนี้ผ่านคุณสมบัติ การห้ามอยู่พร้อมกัน (mutually exclusion)

  24. Algorithm 3 • Pi จะติดอยู่ในประโยค while ก็ต่อเมื่อ flag[j] = true และ turn = j ก่อนที่จะเข้าเขตวิกฤต ถ้า Pjไม่ต้องการเข้าเขตวิกฤตแล้ว flag[j] = false Piก็สามารถเข้าเขตวิกฤตได้ ถ้า Pj ต้องการเข้าโดยให้ flag[j] = true และทำคำสั่ง while ค่าของ turn จะต้องเป็น i หรือ j ค่าใดค่าหนึ่งเท่านั้น ถ้า turn = i Piก็จะเข้าเขตวิกฤตได้ ถ้า turn = j Pjก็จะเข้าเขตวิกฤตได้ หลังจากที่ Pjออกจากเขตวิกฤต Pjก็จะให้ flag[j] = false ซึ่งเป็นผลให้ Piสามารถผ่าน while เข้าเขตวิกฤตได้ แต่ถ้า Pjทำงานเร็วมาก วนไปให้ flag[j] = true (ก่อนเข้าเขตวิกฤต)ได้ ก็จะทำให้ turn = i ดังนั้น Piซึ่งไม่ได้เปลี่ยนค่า turn ในขณะที่ติดอยู่ที่ while ก็จะเข้าเขตวิกฤตได้ (ผ่านคุณสมบัติ ความก้าวหน้า (Progress) โดยรอคอยอย่างมากไม่เกิน 1 รอบที่ Pjเข้าเขตวิกฤต (ผ่านคุณสมบัติ การรอคอยอย่างมีขอบเขต (Bounded Waiting)

  25. การแก้ปัญหาในระบบที่มีหลายกระบวนการ (Multiple-Process Solutions) • Algorithm นี้ เรียกว่า bakery algorithm วิธีนี้มีแนวคิดมาจาก การจัดลำดับลูกค้าที่มาใช้บริการในร้านขายขนมปัง • เมื่อลูกค้าเข้ามาในร้าน จะได้รับหมายเลขบัตรคิว ลูกค้าที่มีหมายเลขน้อยที่สุด จะได้รับบริการก่อน ในกรณีที่ลูกค้า 2 คน อาจได้รับหมายเลขเดียวกัน (เพราะเข้าร้านพร้อมกัน) ให้เรียงลำดับ ด้วยชื่อลูกค้าแทน เช่น ถ้า Piและ Pjได้รับหมายเลขเดียวกัน และ i < j แล้ว Piจะได้รับบริการก่อน

  26. bakery algorithm • โครงสร้างข้อมูลโดยทั่วไปคือ • boolean choosing[n]; • int number[n]; • ค่าเริ่มต้นของ choosing ทั้งหมดเป็น false • และ number = 0 • เพื่อความสะดวก เรากำหนดสัญลักษณ์ดังนี้ • (a,b) < (c,d) ถ้า a < c หรือ ถ้า a = c และ b < d • max(a0 , … , an-1) เป็นฟังก์ชันให้ค่ามากที่สุดจาก a0ถึง an-1

  27. do { • choosing[i] = true; //กระบวนการแรกจะเข้าเขตวิกฤต • number[i] := max(number[0], number[1], … , number[n-1]) + 1; • //ให้ priority (บัตรคิว) คนถัดไป • choosing[i] = false; //นั่งรอก่อน • for (j = 0; j < n; j++) { • while (choosing[j]) • ; //do nothing //ใครอยู่ในเขตวิกฤตก่อนหน้าหรือเปล่า ถ้ามีต้องรอก่อน • while (number [j] != 0 //กระบวนการที่มาทีหลังต้องไม่เป็น 0 ถึงจะได้เข้าเขตวิกฤต • ใครมีหมายเลขบัตรคิวสูงกว่ากัน • && (number[j],j) < (number[i],i)) • ; //do nothing • ถ้าบัตรคิวเบอร์เดียวกัน ดูชื่อของกระบวนการว่าชื่อใครสิทธิสูงกว่า • } • critical section • number[i] = 0; //ออกจากเขตวิกฤต • remainder section • } while (true);

  28. ซีมาฟอร์ (Semaphores) • วิธีการแก้ปัญหาเขตวิกฤต ที่กล่าวมาแล้วทั้งหมด ยังคงไม่สะดวกในการใช้งานกับปัญหาที่ซับซ้อนมากขึ้น เราจึงต้องหาวิธีใหม่ เรียกว่า semaphore semaphore S คือ ตัวแปรชนิด integer ซึ่งสามารถกำหนดค่าเริ่มต้นได้ และใช้งานได้ โดยผ่านคำสั่ง 2 คำสั่ง เท่านั้น คือ wait และ signal คำสั่งทั้งสองนี้ มีนิยามดั้งเดิมดังนี้ • wait(S) { while S 0 • ; //do no-op; • S --; • } • signal(S) { S ++; }

  29. ซีมาฟอร์ (Semaphores) • การใช้งาน(Usage) • เราสามารถใช้ semaphore กับปัญหาเขตวิกฤต ที่มีกระบวนการ n กระบวนการได้ โดยให้ตัวแปรร่วมเป็น • semaphore mutex =1; //mutex เป็น semaphore มีค่า 1; • โปรแกรมสำหรับกระบวนการ Piเป็นดังนี้ • do { • wait(mutex); • critical section • signal(mutex); • remainder section • } while (true);

  30. ซีมาฟอร์ (Semaphores) • เรายังสามารถใช้ semaphore แก้ปัญหาการประสานงาน (synchronization problem)แบบต่าง ๆ ได้อีก เช่น กระบวนการ P1ทำประโยคคำสั่ง S1 และกระบวนการ P2ทำประโยคคำสั่ง S2 โดยทำงานขนานกัน แต่เราต้องการให้ประโยค S2 ทำงานหลังจากที่ประโยค S1 เสร็จเรียบร้อยแล้ว

  31. ซีมาฟอร์ (Semaphores) • เราสามารถใช้ตัวแปรร่วม • semaphore synch = 0; • และเพิ่มคำสั่ง • S1; • signal(synch); • ลงในโปรแกรมของกระบวนการ P1และเพิ่มคำสั่ง • wait(synch); • S2; ลงในกระบวนการ P2 • เนื่องจากค่าเริ่มต้นของ synch เป็น 0 ดังนั้น P2จะทำประโยค S2 ได้ ก็ต่อเมื่อ P1ทำคำสั่ง signal(synch); (ซึ่งหมายความว่า P1 ทำประโยค S1 เสร็จแล้ว

  32. การสร้าง semaphore (Implementation) • วิธีแก้ปัญหาเขตวิกฤตทั้งหมดที่กล่าวมา มีข้อเสียหลักตรงที่ มี “การวนเวียนรอคอย” (busy waiting) เมื่อมีกระบวนการหนึ่ง อยู่ในเขตวิกฤต กระบวนการอื่น ๆ ที่ต้องการเข้าเขตวิกฤตบ้าง ต้องวนเวียนทดสอบค่าก่อนเข้าเขตวิกฤตไปเรื่อย ๆ ย่อมเป็นเหตุให้เวลาของหน่วยประมวลผลกลางเสียไปโดยเปล่าประโยชน์ • เวลาเหล่านี้อาจยกให้กระบวนการอื่น ได้ใช้ประโยชน์คุ้มค่ากว่า semaphore ประเภทนี้ เรียกว่า spinlock คือกระบวนการวนเวียนทำงาน (spin) อยู่ ขณะที่กำลังรอคอยให้เปิดล็อค

  33. การสร้าง semaphore (Implementation) • เราสามารถปรับปรุงนิยามของคำสั่ง wait และ signal ใหม่ เพื่อให้ ไม่มีปัญหา การวนเวียนรอคอย (busy waiting) เมื่อกระบวนการทำคำสั่ง wait และพบว่า ค่าของ semaphore น้อยกว่าหรือเท่ากับ 0 กระบวนการจะต้องรอคอย โดยการหยุดชั่วขณะ (block) แทนที่จะวนเวียนรอคอย การหยุดชั่วขณะนี้ กระบวนการจะเข้าไปรอในแถวคอย (waiting queue) ที่เกี่ยวข้องกับ semaphore นั้น ๆ และเปลี่ยนสถานะเป็น สถานะรอคอย (waiting state) การควบคุมจะถูกย้ายกลับไปที่ตัวจัดตารางการทำงานของหน่วยประมวลผลกลาง เพื่อจัดให้กระบวนการอื่นทำงานต่อไป

  34. การสร้าง semaphore (Implementation) • กระบวนการที่หยุดชั่วขณะ (block) โดยรอ semaphore S นี้ จะสามารถดำเนินต่อได้ เมื่อมีกระบวนการอื่นทำคำสั่ง signal กับ semaphore S ภายในคำสั่ง signal จะมีการปลุก (wakeup) ให้กระบวนการ ที่หยุดชั่วขณะ กลับดำเนินการต่อได้ โดยเปลี่ยนสถานะของกระบวนการนั้นเป็น สถานะพร้อม (ready state) แล้วย้ายไปต่อแถวพร้อม

  35. การสร้าง semaphore (Implementation) • การสร้าง semaphore ตามนิยามใหม่นี้ กำหนดให้ semaphore เป็น struct ในภาษา c • typedef struct { • int value; • struct process *L; • } semaphore;

  36. การสร้าง semaphore (Implementation) • semaphore จะประกอบด้วย ตัวเลขจำนวนเต็ม (ตัวแปร value) และแถวคอยของกระบวนการ (ตัวแปร L) เมื่อกระบวนการหนึ่งต้องคอย semaphore นี้ มันก็จะถูกใส่ชื่อลงในแถวคอย L การใช้คำสั่ง signal จะดึงกระบวนการออกจากหัวแถวคอยนี้ และปลุกกระบวนการที่ได้ ให้กลับไปทำงานต่อ เราจึงแก้ไขโปรแกรมคำสั่งเป็นดังนี้

  37. การสร้าง semaphore (Implementation) • void wait(semaphore S) { • S.value - -; • if (S.value < 0) { • add this process to S.L (list); • block(); • } • } • void signal(semaphore S) { • S.value ++; • if (S.value <= 0) { • remove a process P from S.L (list); • wakeup(P); • } • }

  38. การสร้าง semaphore (Implementation) • คำสั่ง block จะทำให้กระบวนการที่ทำคำสั่งนี้ หยุดชั่วขณะ • คำสั่ง wakeup(P) จะปลุกกระบวนการ P ให้กลับทำงานต่อ • จะสังเกตได้ว่า นิยามดั้งเดิมของ semaphore ซึ่งมีการวนเวียนรอคอยนั้น ค่าของ semaphore จะไม่ติดลบ • แต่ในนิยามใหม่นี้ ค่าของ semaphore มีค่าเป็นลบได้ ค่าที่เป็นลบแสดงถึงจำนวนกระบวนการที่รอคอย semaphore ตัวนั้น ๆ ด้วย • เราต้องไม่ให้มีกระบวนการสองตัวทำคำสั่ง wait และ signal บน semaphore ตัวเดียวกัน ในเวลาเดียวกัน ซึ่งกรณีนี้ ก็คือ ปัญหาเขตวิกฤตแบบหนึ่งนั่นเอง โดยสามารถเลือกวิธีจัดการได้ 2 วิธี คือ

  39. การสร้าง semaphore (Implementation) • ถ้าเป็นระบบที่มีหน่วยประมวลผลเพียงตัวเดียว เราก็เพียงแต่ห้ามขัดจังหวะ (interrupt) ขณะที่กำลังทำงานคำสั่ง wait และ signal ดังนั้นกระบวนการอื่น จะไม่สามารถมาขัดจังหวะการทำงานได้ • ถ้าเป็นระบบที่มีหน่วยประมวลผลหลายตัว การห้ามขัดจังหวะ จะไม่เพียงพอเพราะกระบวนการอื่น อาจทำงานอยู่ในหน่วยประมวลผล คนละตัวกับ กระบวนการที่ห้ามขัดจังหวะ เราอาจจัดการ โดยใช้ขั้นตอนวิธี ในหัวข้อ 6.2 (critical section) แล้วเอาคำสั่ง wait และ signal ใส่ไว้ในเขตวิกฤต ก็จะสามารถป้องกันได้

  40. แม่แบบของปัญหาในการประสานงาน (Classical Problems of Synchronization) • ปัญหาที่พักข้อมูลขนาดจำกัด • (The Bounded-Buffer Problem) • ปัญหาผู้อ่าน-ผู้เขียน • (The Readers and Writers Problem) • ปัญหาอาหารเย็นของนักปราชญ์ • (The Dining-Philosopher’ s Problem)

  41. ปัญหาที่พักข้อมูลขนาดจำกัด (The Bounded-Buffer Problem) • กำหนดให้ ที่พักข้อมูลมีขนาด n ช่อง แต่ละช่องเก็บข้อมูลได้ 1 ตัว ให้ semaphore mutex มีค่าเริ่มต้นเป็น 1 ตัวป้องกันการใช้ที่พักข้อมูลคือ semaphore emptyและ fullเป็นตัวนับว่า ที่พักข้อมูล มีจำนวนช่องว่าง และ ช่องเต็ม(มีข้อมูลอยู่) กี่ช่อง โดย emptyมีค่าเริ่มต้นเป็น n และ fullมีค่าเริ่มต้น เป็น 0

  42. ปัญหาที่พักข้อมูลขนาดจำกัด (The Bounded-Buffer Problem) • do { • … • produce an item in nextp • … • wait(empty); • wait(mutex); • … • add nextp to buffer • … • signal(mutex); • signal(full); • } while (true); • โครงสร้างของกระบวนการผู้ผลิต

  43. ปัญหาที่พักข้อมูลขนาดจำกัด (The Bounded-Buffer Problem) • do { • wait(full); • wait(mutex); • … • remove an item from buffer to nextc • … • signal(mutex); • signal(empty); • … • consume the item in nextc • … • } while (true); • โครงสร้างของกระบวนการผู้ใช้

  44. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • กลุ่มของกระบวนการเหล่านี้ ออกเป็น 2 พวก คือ • พวกที่ต้องการอ่านอย่างเดียว เรียกว่า “ผู้อ่าน” (readers) • ส่วนพวกที่เหลือ เรียกว่า “ผู้เขียน” (writers) • จะเห็นได้ว่า ผู้อ่านหลายคน อาจอ่านข้อมูลร่วมกันได้พร้อม ๆ กัน โดยไม่เสียหาย แต่ผู้เขียน 1 คน กับอีกคนหนึ่ง (ซึ่งอาจเป็น ผู้อ่าน หรือ ผู้เขียนก็ได้) ไม่อาจทำการพร้อม ๆ กัน บนข้อมูลร่วมนี้ได้

  45. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • เพื่อป้องกันปัญหานี้ เราต้องให้ผู้เขียน ใช้ข้อมูลร่วม เพียงคนเดียวในขณะหนึ่ง ๆ ปัญหาการประสานงานแบบนี้ เราเรียกว่า ปัญหาผู้อ่าน-ผู้เขียน (Readers-Writers Problem) • หมายความว่า ถ้าข้อมูลร่วม มีผู้อ่านคนอื่น กำลังอ่านอยู่ ผู้ที่เข้ามาใหม่สามารถใช้ข้อมูลร่วมได้เลย แม้ว่า จะมีผู้เขียนรอใช้อยู่ก็ตาม • แบบที่ 2 เมื่อผู้เขียนพร้อม ผู้เขียนจะสามารถใช้ข้อมูลร่วมได้เร็วที่สุดเท่าที่จะทำได้ หมายความว่า เมื่อมีผู้เขียนรออยู่ ผู้อ่านใหม่ห้ามเข้าไปอ่านร่วม

  46. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • ในการแก้ปัญหาผู้อ่าน-ผู้เขียนแบบแรก กำหนดให้ตัวแปรร่วมเป็นดังนี้ • semaphore mutex=1, wrt =1; • int readcount = 0; • ตัวแปร readcount เป็นตัวนับจำนวน ผู้อ่านที่กำลังอ่านอยู่ semaphore mutexใช้ป้องกันตัวแปร readcount semaphore wrt ใช้ป้องกันผู้เขียน ผู้อ่านคนแรก และคนสุดท้าย ที่เข้าและออกจากเขตวิกฤตต้องใช้ semaphore wrtด้วย ส่วนผู้อ่านคนกลาง ๆ ไม่ต้องใช้ semaphore wrt

  47. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • wait(wrt); • … • writing is performed • … • signal(wrt); • โครงสร้างของกระบวนการผู้เขียน

  48. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • wait(mutex); • readcount ++; • if (readcount == 1) • wait(wrt); • signal(mutex); • … • reading is performed • … • wait(mutex); • readcount --; • if (readcount == 0) • signal(wrt); • signal(mutex); • โครงสร้างของกระบวนการผู้อ่าน

  49. ปัญหาผู้อ่าน-ผู้เขียน(The Readers and Writers Problem) • สังเกตว่า ถ้าผู้เขียนอยู่ในเขตวิกฤต และมีผู้อ่านรออยู่ n คน ผู้อ่าน 1 คนจะรออยู่ที่ semaphore wrtส่วนผู้อ่าน n – 1 คน จะรออยู่ที่ semaphore mutexและเมื่อผู้เขียนทำคำสั่ง signal(wrt) อาจไปปลุกผู้อ่านทั้งหมด หรือผู้เขียน 1 คน ซึ่งรออยู่ก็ได้ ขึ้นอยู่กับการออกแบบตัวจัดตารางแถวคอย

  50. ปัญหาอาหารเย็นของนักปราชญ์The Dining-Philosopher’ s Problem)

More Related