Peterson sử dụng các dữ liệu gì?

Khái niệm cơ bản

Critical section

Các giải pháp dùng lệnh máy thông thường

Giải thuật Peterson, và giải thuật bakery

Các giải pháp dùng lệnh cấm ngắt hoặc lệnh máy đặc biệt

Semaphore

Semaphore và các bài toán đồng bộ

Monitor

Bạn đang xem trước 20 trang nội dung tài liệu Hệ điều hành - Chương 3: Đồng bộ quá trình, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên

-1.*-Chương 3 Đồng Bộ Quá Trình*Nội dungKhái niệm cơ bảnCritical section Các giải pháp dùng lệnh máy thông thườngGiải thuật Peterson, và giải thuật bakeryCác giải pháp dùng lệnh cấm ngắt hoặc lệnh máy đặc biệtSemaphoreSemaphore và các bài toán đồng bộMonitor*Bài toán đồng bộ [1/2]Khảo sát các process/thread thực thi đồng thời và chia sẻ dữ liệu [ghi shared memory] trong hệ thốnguniprocessor, hoặcshared memory multiprocessorNếu không có sự kiểm soát khi truy cập các dữ liệu chia sẻ thì chúng có thể trỡ nên không nhất quán.Để duy trì sự nhất quán dữ liệu, hệ thống cần có cơ chế bảo đảm sự thực thi có trật tự của các process đồng thời.*Bài toán đồng bộ [2/2]Hai lớp bài toán đồng bộ:Hợp tácBài toán producer-consumer: bounded bufferCấp phát tài nguyênBài toán loại trừ tương hỗ: đồâng bộ nhiều quá trình sử dụng một tài nguyên không chia sẻ đồâng thời đượcBài toán Dining Philosophers*Shared memoryBiến chia sẻquá trình 2quá trình 1Quá trinh 1 và 2 code và private dataĐồng thời  song songTrên uniprocessor hay trên shared memory multiprocessor, các quá trình chạy đồng thờiTrên shared memory multiprocessor, các quá trình có thể chạy song song*Bài toán Producer-consumer [1/3]Ví dụ Bounded buffer, thêm biến đếm count #define BUFFER_SIZE 8 /* 8 buffers */ typedef struct { . . . } item; item buffer[BUFFER_SIZE]; int in = 0, out = 0, count = 0;*Bài toán Producer-consumer [2/3] Quá trình Produceritem nextProduced;while[1] { while [count == BUFFER_SIZE]; buffer[in] = nextProduced; count++; in = [in + 1] % BUFFER_SIZE;}Quá trình Consumeritem nextConsumed;while[1] { while [count == 0]; nextConsumed = buffer[out]; count--; out = [out + 1] % BUFFER_SIZE;}biến count được chia sẻgiữa producer và consumer*Bài toán Producer-consumer [3/3]Các lệnh tăng/giảm biến count tương đương trong ngôn ngữ máy là:Producer count++:register1 = countregister1 = register1 + 1count = register1Consumer count--:register2 = countregister2 = register2 - 1count = register2Trong đó, registeri là thanh ghi của CPU. *Đồng bộ và lệnh đơn nguyênMã máy của các lệnh tăng và giảm biến count có thể thực thi xen kẽGiả sử count đang bằng 5. Chuỗi thực thi sau có thể xảy ra: 1: producer register1 := count {register1 = 5} producer register1 := register1 + 1 {register1 = 6} 2: consumer register2 := count {register2 = 5} consumer register2 := register2 - 1 {register2 = 4} 3: producer count := register1 {count = 6} 4: consumer count := register2 {count = 4}Cả hai process thao tác đồng thời lên biến chung count. Trị của biến chung này không nhất quán dưới các thao tác của hai process. Giải pháp: các lệnh count++, count-- phải là đơn nguyên [atomic], nghĩa là thực hiện như một lệnh đơn, không thực thi đan xen nhau.*Race conditionRace condition: nhiều process truy xuất và thao tác đồng thời lên dữ liệu chia sẻ [như biến count]; kết quả cuối cùng của việc truy xuất đồng thời này phụ thuộc thứ tự thực thi của các lệnh thao tác dữ liệu.Để dữ liệu chia sẻ được nhất quán, cần bảo đảm sao cho các process lần lượt thao tác lên dữ liệu chia sẻ. Do đó, cần có cơ chế đồng bộ hoạt động của các process này.*Khái niệm Critical SectionGiả sử có n process đồng thời truy xuất dữ liệu chia sẻ.Giải quyết vấn đề race condition cho những đoạn code có chứa các thao tác lên dữ liệu chia sẻ. Đoạn code này được gọi là vùng tranh chấp [critical section, CS].Bài toán loại trừ tương hỗ: phải bảo đảm sự loại trừ tương hỗ [mutual exclusion, mutex], tức là khi một process P đang thực thi trong CS của P, không có process Q nào khác đồng thời thực thi các lệnh trong CS của Q.*Cấu trúc tổng quát của quá trình trong bài toán loại trừ tương hỗGiả sử mỗi process thực thi bình thường [i.e., nonzero speed] và không có sự tương quan giữa tốc độ thực thi của các processCấu trúc tổng quát của một process:Một số giả địnhCó thể có nhiều CPU nhưng phần cứng không cho phép nhiều tác vụ truy cập một vị trí trong bộ nhớ cùng lúcKhông ràng buộc về thứ tự thực thi của các processCác process có thể chia sẻ một số biến chung nhằm đồng bộ hoạt động của chúngVấn đềThiết kế entry section và exit sectiondo { critical section remainder section} while[1];entry sectionexit section*Định nghĩa lời giải của bài toán loại trừ tươnghỗ Lời giải phải thỏa ba tính chất1. Mutual exclusion2. Progress[Progress cho entry section] Nếu ít nhất một process đang trong entry section và không có process nào đang trong critical section, thì một process vào critical section tại một thời điểm sau đó. [Progress cho exit section] Nếu ít nhất một process đang trong exit section, thì một process vào remainder section tại một thời điểm sau đó.3. Starvation freedom [lockout-freedom][cho entry section] quá trình vào entry section sẽ vào CS[cho exit section] quá trình vào exit section sẽ vào remainder section.*Phân loại giải pháp cho bài toán loại trừ tương hỗGiải pháp dùng lệnh máy thông thườngGiải pháp dùng lệnh cấm ngắt hay lệnh máy đặc biệtLệnh Disable interruptLệnh máy đặc biệt nhưTestAndSet*Giải pháp dùng lệnh máy thông thườngGiải pháp cho 2 process đồng thờiGiải thuật 1 và 2Giải thuật Peterson cho 2 processGiải pháp cho n processGiải thuật bakery*Giải thuật 1 [1/2]Biến chia sẻint turn; /* khởi đầu turn = 0 */nếu turn = i thì Pi được phép vào critical section, với i = 0 hay 1Process Pi do { while [turn != i]; critical section turn = j; remainder section } while [1];Giải thuật thoả mãn mutual exclusion [1], nhưng không thoả mãn tính chất progress [2] vì tính chất strict alternation của giải thuật*Process P0do { while [turn != 0]; critical section turn := 1; remainder section} while [1];Process P1do { while [turn != 1]; critical section turn := 0; remainder section} while [1];Giải thuật không thỏa mãn tính chất Progress [Progress cho entry section]:Nếu turn = 0, P0 được vào CS và sau đó gán turn = 1 và vào remainder section [RS]; giả sử P0 “ở lâu” trong đó.Lúc đó P1 vào CS và sau đó gán turn = 0, kế đó P1 vào và xong RS, vào entry section, đợi vào CS một lần nữa; nhưng vì turn = 0 nên P1 phải chờ P0.Giải thuật 1 [2/2][viết lại]*Giải thuật 2Biến chia sẻboolean flag[ 2 ]; /* khởi đầu flag[ 0 ] = flag[ 1 ] = false */Nếu flag[ i ] = true thì Pi “sẵn sàng” vào critical section.Process Pi do { flag[ i ] = true; while [ flag[ j ] ]; /* Pi “nhường” Pj */ critical section flag[ i ] = false; remainder section } while [1];*Giải thuật 2 [tiếp][copy lại]Process P0 do { flag[ 0 ] = true; while [flag[ 1 ]]; critical section flag[ 0 ] = false; remainder section } while [1];Process P1 do { flag[ 1 ] = true; while [flag[ 0 ]]; critical section flag[ 1 ] = false; remainder section } while [1];- Bảo đảm được mutual exclusion. Chứng minh?- Không thỏa mãn progress. Vì sao? Nếu đồng thời P0 gán flag[ 0 ] = true P1 gán flag[ 1 ] = true  P0 và P1 loop mãi mãi trong vòng lặp while*Giải thuật Peterson cho 2 process [1/2]Biến chia sẻ: kết hợp cả giải thuật 1 và 2Process Pi , với i = 0 hay 1 do { flag[ i ] = true; /* Process i sẵn sàng */ turn = j; /* Nhường process j */ while [flag[ j ] and turn == j ]; critical section flag[ i ] = false; remainder section } while [1];*Process P0do { flag[0] = true; turn = 1; while [flag[1] && turn == 1]; critical section flag[0] = false; remainder section} while[1];Process P1do { flag[1] = true; turn = 0; while [flag[0] && turn == 0]; critical section flag[1] = false; remainder section} while[1];Giải thuật Peterson cho 2 process [2/2][viết lại]*Giải thuật Peterson cho 2 process: Tính đúng đắnMutual exclusion được bảo đảmChứng minh bằng phản chứng:Nếu P0 và P1 cùng ở trong CS thì flag[0] = flag[1] = true, suy ra từ điều kiện của vòng lặp while sẽ có turn = 0 [trong P0] và turn = 1 [trong P1]. Điều không thể xảy ra.Chứng minh thỏa yêu cầu về progress và lock-out freedomXem tài liệu*Giải thuật bakery [1/3]n processTrước khi vào CS, process Pi nhận một con số. Process nào giữ con số nhỏ nhất thì được vào CS.Trường hợp Pi và Pj cùng nhận được một con số: Nếu i < j thì Pi được vào trước.Khi ra khỏi CS, Pi gán lại số của mình bằng 0.Cách cấp số cho các process thường tạo các số tăng dần, ví dụ 1, 2, 3, 3, 3, 3, 4, 5,Kí hiệu[a,b] < [c,d] nếu a < c hoặc nếu a = c và b < dmax[a0,,ak ] là con số b sao cho b  ai với mọi i = 0,, k*Giải thuật bakery [2/3] /* shared variable */ boolean choosing[ n ]; /* initially, choosing[ i ] = false */ int num[ n ]; /* initially, num[ i ] = 0 */ do { choosing[ i ] = true; num[ i ] = max[num[0], num[1],, num[n  1]] + 1; choosing[ i ] = false; for [ j = 0; j < n; j++] { while [choosing[ j ]]; while [[num[ j ] != 0] && [num[ j ], j] < [num[ i ], i]]; } critical section num[ i ] = 0; remainder section } while [1];*Giải thuật bakery [3/3]Giải thuật bakery bảo đảmMutual exclusionProgressLockout freedom*Nhận xétCác giải thuật vừa được trình bày chỉ dùng lệnh máy thông thườngCác process khi yêu cầu được vào vùng tranh chấp đều phải liên tục kiểm tra điều kiện [busy waiting], tốn thời gian xử lý của CPU.Nếu thời gian xử lý trong vùng tranh chấp lớn, một giải pháp hiệu quả nên có cơ chế block các process cần đợi.*Dùng lệnh cấm ngắtTrong hệ thống uniprocessor: mutual exclusion được bảo đảm.Nhưng nếu system clock được cập nhật do interrupt thì Trên hệ thống multiprocessor: mutual exclusion không được đảm bảo vìChỉ cấm ngắt tại CPU thực thi lệnh disable interruptsCác CPU khác vẫn có thể truy cập bộ nhớ chia sẻProcess Pi:do { disable_interrupts[]; critical section enable_interrupts[]; remainder section} while [1];*Dùng các lệnh máy đặc biệtÝ tưởngViệc truy xuất vào vào một địa chỉ của bộ nhớ vốn đã có tính loại trừ tương hỗ [chỉ có một thao tác truy xuất tại một thời điểm]Mở rộngThiết kế một lệnh máy đơn nguyên có thể thực hiện hai thao tác trên cùng một ô nhớ [vd: read và write]Việc thực thi các lệnh máy như trên luôn bảo đảm mutual exclusion, ngay cả với multiprocessor Các lệnh máy đặc biệt có thể đảm bảo mutual exclusion nhưng cần kết hợp với một số cơ chế khác để thoả mãn progress, tránh starvation và deadlock*Lệnh TestAndSet [1/2]Đọc và ghi một biến chia sẻ bằng một lệnh đơn nguyênboolean TestAndSet[boolean &target] { boolean rv = target; target = true; /* set */ return rv;}Áp dụng TestAndSet Shared data: boolean lock = false; Process Pi : do { while [TestAndSet[lock]]; critical section lock = false; remainder section } while [1];Nếu TestAndSet không đơn nguyên, tình huống xấu nào có thể xảy ra cho giải thuật trên?*Lệnh TestAndSet [2/2]Mutual exclusion được bảo đảm: nếu Pi vào CS, các process Pj khác đều đang busy waiting hoặc trong remainder sectionKhi Pi ra khỏi CS, sự chọn lựa process Pj vào CS kế tiếp là tùy ý  starvation * Lệnh Swap [1/2]Các processor [ví dụ Pentium] thông thường cung cấp một lệnh máy đơn nguyên là Swap[a, b] có tác dụng hoán chuyển trị của a và b.Swap[a, b] cũng có ưu nhược điểm như TestAndSet* Lệnh Swap [2/2]Lệnh đơn nguyênvoid Swap[boolean &a, boolean &b] { boolean temp = a; a = b; b = temp;}Áp dụngBiến chia sẻbool lock = false; Process Pi : do { key = true; while [key == true] Swap[lock, key]; critical section lock = false; remainder section } while [1] Không thỏa mãn starvation freedom*Giải thuật dùng TestAndSet thoả mãn 3 yêu cầu [1/2]waiting[ i ] = true;key = true;while [waiting[ i ] && key] key = TestAndSet[lock];waiting[ i ] = false;j = [i + 1] % n;while [[ j != i] && !waiting[ j ]] j = [ j + 1] % n;if [ j == i] lock = false;else waiting[ j ] = false;critical sectionremainder sectiondo {} while [1]Biến chia sẻ,khởi tạo là falsebool waiting[ n ];bool lock;*Giải thuật dùng TestAndSet thoả mãn 3 yêu cầu [2/2]Mutual exclusion: Pi chỉ có thể vào CS nếu và chỉ nếu hoặc waiting[ i ] = false, hoặc key = falsekey = false chỉ khi TestAndSet được thực thi lên lock mà trả về false; các process khác đều phải đợiwaiting[ i ] = false chỉ khi process khác rời khỏi CSChỉ có một waiting[ i ] có giá trị falseProgressLockout-freedom: waiting in cyclic order*SemaphoreSemaphore là công cụ đồng bộ cung cấp bởi OS.semaphore, ngoài thao tác khởi động biến cùng với trị ban đầu, chỉ có thể được truy xuất qua hai tác vụwait[S] hay còn gọi là P[S]: giảm trị semaphore, nếu trị này âm thì process gọi lệnh bị blocked.signal[S] hay còn gọi là V[S]: tăng trị semaphore, nếu trị này không dương, một process đang blocked bởi gọi lệnh wait[] trước đó sẽ được phục hồi để thực thi.Semaphore giúp process tránh busy waiting: khi phải đợi thì process sẽ được đặt vào một blocked queue, trong đó chứa các process đang chờ đợi cùng một sự kiện.Nhưng có thể cần busy waiting để hiện thực chính semaphore*Hiện thực semaphore [1/3]Hiện thực semaphore là một record typedef struct { int value; struct process *L; /* process queue */ } semaphore; cùng với các tác vụ lên nóGiả sử hệ điều hành cung cấp hai tác vụ:block[]: tạm treo process nào thực thi lệnh này, trạng thái running  waitingwakeup[P]: phục hồi process P đang blocked, trạng thái waiting  ready*Hiện thực semaphore [2/3]Các tác vụ semaphore được hiện thực như sau void wait[semaphore S] { S.value--; if [S.value < 0] { add this process to S.L; block[]; } } void signal[semaphore S] { S.value++; if [S.value

Chủ Đề