Professional Documents
Culture Documents
1 2
1
Tương tranh và đồng bộ Khái niệm về đoạn mã găng (1)
z Tình huống xuất hiện khi nhiều tiến trình cùng z Thuật ngữ: Critical section
thao tác trên dữ liệu chung và kết quả các z Thuật ngữ tiếng Việt: Đoạn mã găng, đoạn
thao tác đó phụ thuộc vào thứ tự thực hiện mã tới hạn.
của các tiến trình trên dữ liệu chung gọi là tình z Xét một hệ có n tiến trình P0, P1, ..., Pn, mỗi
huống tương tranh (race condition) tiến trình có một đoạn mã lệnh gọi là đoạn
z Để tránh các tình huống tương tranh, các tiến mã găng, ký hiệu là CSi, nếu như trong đoạn
trình cần được đồng bộ theo một phương mã này, các tiến trình thao tác trên các biến
thức nào đó ⇒ Vấn đề nghiên cứu: Đồng bộ chung, đọc ghi file... (tổng quát: thao tác trên
hóa các tiến trình dữ liệu chung)
7 8
Khái niệm về đoạn mã găng (2) Khái niệm về đoạn mã găng (3)
z Đặc điểm quan trọng mà hệ n tiến trình này z Cấu trúc chung của Pi để thực hiện đoạn mã
cần có là: Khi một tiến trình Pi thực hiện đoạn găng CSi.
mã CSi thì không có tiến trình Pj nào khác do {
được phép thực hiện CSj Xin phép (ENTRYi) thực hiện CSi; // Entry section
z Mỗi tiến trình Pi phải “xin phép” (entry Thực hiện CSi;
section) trước khi thực hiện CSi và thông báo Thông báo (EXITi) đã thực hiện xong CSi; // Exit section
(exit section) cho các tiến trình khác sau khi Phần mã lệnh khác (REMAINi); // Remainder section
thực hiện xong CSi. } while (TRUE);
9 10
Khái niệm về đoạn mã găng (4) Giải pháp cho đoạn mã găng
z Viết lại cấu trúc chung của đoạn mã găng: z Giải pháp cho đoạn mã găng cần thỏa mãn 3
điều kiện:
do {
z Loại trừ lẫn nhau (mutual exclusion): Nếu Pi đang
ENTRYi; // Entry section thực hiện CSi thì Pj không thể thực hiện CSj ∀j≠i.
Thực hiện CSi; // Critical section z Tiến triển (progress): Nếu không có tiến trình Pi nào
EXITi; // Exit section thực hiện CSi và có m tiến trình Pj1, Pj2, ..., Pjm muốn
thực hiện CSj1, CSj2, ..., CSjm thì chỉ có các tiến trình
REMAINi; // Remainder section không thực hiện REMAINjk (k=1,...,m) mới được xem
} while (TRUE); xét thực hiện CSjk.
z Chờ có giới hạn (bounded waiting): sau khi một tiến
trình Pi có yêu cầu vào CSi và trước khi yêu cầu đó
11
được chấp nhận, số lần các tiến trình Pj (với j≠i) được
12
phép thực hiện CSj phải bị giới hạn.
2
Ví dụ: giải pháp của Peterson Ví dụ: giải pháp của Peterson
z Giả sử có 2 tiến trình P0 và P1 với hai đoạn z Mã lệnh của Pi:
mã găng tương ứng CS0 và CS1 do {
z Sử dụng một biến nguyên turn với giá trị khởi flag[i] = TRUE;
tạo 0 hoặc 1 và mảng boolean flag[2] turn = j;
z turn có giá trị i có nghĩa là Pi được phép thực while (flag[j] && turn == j) ;
hiện CSi (i=0,1) CSi;
z nếu flag[i] là TRUE thì tiến trình Pi đã sẵn flag[j] = FALSE;
sàng để thực hiện CSi REMAINi;
} while (1);
13 14
15 16
3
Toán tử wait và signal Sử dụng semaphore (1)
wait(S) // hoặc P(S) signal(S) // hoặc V(S) z Với bài toán đoạn mã găng:
{ { do {
while (S<=0); S++;
wait(mutex); // mutex là semaphore khởi tạo 1
S--; }
CSi;
}
signal(mutex);
z Toán tử wait: Chờ khi z Toán tử signal: Tăng S REMAINi;
semaphore S âm và lên 1 } while (1);
giảm S đi 1 nếu S>0
19 20
Cài đặt semaphore theo cấu trúc Cài đặt semaphore theo cấu trúc
z Khắc phục chờ bận: Chuyển vòng lặp chờ void wait(semaphore *S) void signal(semaphore *S)
thành việc sử dụng toán tử block (tạm dừng) { {
z Để khôi phục thực hiện từ block, ta có toán tử S->value--; S->value++;
wakeup if (S->value<0) { if (S->value<=0) {
z Khi đó để cài đặt, ta có cấu trúc dữ liệu mới Thêm tiến trình gọi Xóa một tiến trình P
cho semaphore: toán tử vào s->L; ra khỏi s->L;
typedef struct { block(); wakeup(P);
int value; // Giá trị của semaphore } }
struct process *L; // Danh sách tiến trình chờ... } }
} semaphore; 23 24
4
Semaphore nhị phân
Một số bài toán
Là semaphore chỉ nhận giá trị 0 hoặc 1
z
25 26
Bài toán vùng đệm có giới hạn Bài toán vùng đệm có giới hạn
z Đã xét ở ví dụ đầu tiên (the bounded-buffer Tiến trình ghi P: Tiến trình đọc Q:
problem) do { do {
z Ta sử dụng 3 semaphore tên là full, empty và wait(empty); wait(full);
mutex để giải quyết bài toán này wait(mutex); wait(mutex);
z Khởi tạo: // Ghi một phần tử mới // Đọc một phần tử ra
z full: Số lượng phần tử buffer đã có dữ liệu (0) // vào buffer // khỏi buffer
z empty: Số lượng phần tử buffer chưa có dữ liệu (n) signal(mutex); signal(mutex);
z mutex: 1 (Chưa có tiến trình nào thực hiện đoạn signal(full); signal(empty);
mã găng) } while (TRUE); } while (TRUE);
27 28
Bài toán tiến trình đọc - ghi Bài toán tiến trình đọc-ghi số 1
z Thuật ngữ: the reader-writer problem z Sử dụng các semaphore với giá trị khởi tạo:
z Tình huống: Nhiều tiến trình cùng thao tác trên một cơ wrt (1), mutex (1)
sở dữ liệu trong đó
z Sử dụng biến rcount (khởi tạo 0) để đếm số
z Một vài tiến trình chỉ đọc dữ liệu (ký hiệu: reader)
z Một số tiến trình vừa đọc vừa ghi (ký hiệu: writer)
lượng reader đang đọc dữ liệu
z Khi có đọc/ghi đồng thời của nhiều tiến trình trên cùng z wrt: Đảm bảo loại trừ lẫn nhau khi writer ghi
một cơ sở dữ liệu, có 2 bài toán: z mutex: Đảm bảo loại trữ lẫn nhau khi cập
z Bài toán 1: reader không phải chờ, trừ khi writer đã được phép nhật biến rcount
ghi vào CSDL (hay các reader không loại trừ lẫn nhau khi đọc)
z Bài toán 2: Khi writer đã sẵn sàng ghi, nó sẽ được ghi trong
thời gian sớm nhất (nói cách khác khi writer đã sẵn sàng,
không cho phép các reader đọc dữ liệu) 29 30
5
Bài toán tiến trình đọc-ghi số 1 Bữa ăn tối của các triết gia
z Tiến trình writer Pw: z Tiến trình reader Pr: z Thuật ngữ: the dining-
do { do { philosophers problem
wait(wrt); wait(mutex); z Có 5 triết gia, 5 chiếc
// Thao tác ghi đang được rcount++; đũa, 5 bát cơm và một
// thực hiện if (rcount==1) wait(wrt); âu cơm bố trí như hình
signal(wrt); signal(mutex); vẽ
while (TRUE); // Thực hiện phép đọc z Đây là bài toán cổ điển
wait(mutex);
và là ví dụ minh họa
cho một lớp nhiều bài
rcount--;
toán tương tranh
if (rcount==0) signal(wrt); (concurrency): Nhiều
signal(mutex); tiến trình khai thác
} while (TRUE); 31
nhiều tài nguyên chung 32
Bữa ăn tối của các triết gia Giải pháp cho bài toán Bữa ăn...
z Mã lệnh của triết gia i:
z Các triết gia chỉ làm 2 việc: Ăn và suy nghĩ z Biểu diễn 5 chiếc đũa qua
mảng semaphore: do {
z Suy nghĩ: Không ảnh hưởng đến các triết gia khác,
semaphore chopstick[5]; wait(chopstick[i]);
đũa, bát và âu cơm
các semaphore được khởi tạo wait(chopstick[(i+1)%5];
z Để ăn: Mỗi triết gia phải có đủ 2 chiếc đũa gần nhất ở giá trị 1 // Ăn...
bên phải và bên trái mình; chỉ được lấy 1 chiếc đũa z Mã lệnh của triết gia như hình signal(chopstick[i]);
một lần và không được phép lấy đũa từ tay triết gia bên
signal(chopstick[(i+1)%5];
khác z Mã lệnh này có thể gây bế tắc
// Suy nghĩ...
(deadlock) nếu cả 5 triết gia
z Khi ăn xong: Triết gia bỏ cả hai chiếc đũa xuống bàn } while (TRUE);
đều lấy được 1 chiếc đũa và
và tiếp tục suy nghĩ chờ để lấy chiếc còn lại nhưng
không bao giờ lấy được!!
33 34
6
Ví dụ hạn chế của semaphore (1) Ví dụ hạn chế của semaphore (2)
z Xét ví dụ về đoạn mã găng: z Xét ví dụ về đoạn mã găng:
z Mã đúng: z Mã sai: z Mã đúng: z Mã sai:
... ... ... ...
wait(mutex); signal(mutex); wait(mutex); wait(mutex);
// Đoạn mã găng // Đoạn mã găng // Đoạn mã găng // Đoạn mã găng
signal(mutex); wait(mutex); signal(mutex); wait(mutex);
... ... ... ...
z Đoạn mã sai này gây ra z Đoạn mã sai này gây ra
vi phạm điều kiện loại bế tắc
trữ lẫn nhau 37 38
Ví dụ hạn chế của semaphore (3) Ví dụ hạn chế của semaphore (4)
z Nếu người lập trình quên các toán tử wait() z Tiến trình P1 z Tiến trình P2
hoặc signal() trong trong các đoạn mã găng, ... ...
hoặc cả hai thì có thể gây ra: wait(S); wait(Q);
z Bế tắc wait(Q); wait(S);
z Vi phạm điều kiện loại trừ lẫn nhau ... ...
signal(S); signal(Q);
signal(Q); signal(S);
7
Monitor là gì? Định nghĩa tổng quát
z Thuật ngữ monitor: giám sát z Monitor là một cách tiếp cận để đồng bộ hóa
z Định nghĩa không hình thức: Là một loại các tác vụ trên máy tính khi phải sử dụng các
tài nguyên chung. Monitor thường gồm có:
construct trong ngôn ngữ bậc cao dùng để
z Tập các procedure thao tác trên tài nguyên chung
phục vụ các thao tác đồng bộ hóa
z Khóa loại trừ lẫn nhau
z Monitor được nghiên cứu, phát triển để khắc z Các biến tương ứng với các tài nguyên chung
phục các hạn chế của semaphore như đã z Một số các giả định bất biến nhằm tránh các tình
nêu trên huống tương tranh
z Trong bài này: Nghiên cứu một loại cấu trúc
monitor: Kiểu monitor (monitor type)
43 44
8
Kiểu condition Monitor có kiểu condition
z Khai báo:
condition x, y; // x, y là các biến kiểu condition
z Sử dụng kiểu condition: Chỉ có 2 toán tử là
wait và signal
z x.wait(): tiến trình gọi đến x.wait() sẽ được chuyển
sang trạng thái chờ (wait hoặc suspend)
z x.signal(): tiến trình gọi đến x.signal() sẽ khôi
phục việc thực hiện (wakeup) một tiến trình đã gọi
đến x.wait()
49 50
Bài toán Ăn tối.. với monitor Monitor của bài toán Ăn tối...
z Giải quyết bài toán Ăn tối của các triết gia với monitor dp {
monitor để không xảy ra bế tắc khi hai triết gia ngồi enum {thinking, hungry, eating} state[5];
cạnh nhau cùng lấy đũa để ăn
condition self[5];
z Trạng thái của các triết gia:
void pickup(int i) {
enum {thinking, hungry, eating} state[5];
state[i] = hungry;
z Triết gia i chỉ có thể ăn nếu cả hai người ngồi cạnh
ông ta không ăn: test(i);
(state[(i+4)%5]!=eating) and (state[(i+1)%5]!=eating) if (state[i] != eating) self[i].wait();
z Khi triết gia i không đủ điều kiện để ăn: cần có biến }
condition: condition self[5]; }
53 54
9
Monitor của bài toán Ăn tối... Monitor của bài toán Ăn tối...
void putdown(int i) { void test(int i) {
state[i] = thinking; if ((state[(i+4)%5] != eating) &&
test((i+4)%5); (state[i] == hungry) &&
test((i+1)%5); (state[(i+1)%5] != eating)) {
} state[i] = eating;
initialization_code() { self[i].signal();
for (int i=0;i<5;i++) state[i] = thinking; }
} }
55 56
10