Tắc nghẽn (Deadlock)
Tắc nghẽn (Deadlock)
Bởi:
Giảng viên . Trần Hạnh Nhi
Định nghĩa:
Một tập hợp các tiến trình được định nghĩa ở trong tình trạng tắc nghẽn khi mỗi tiến
trình trong tập hợp đều chờ đợi một sự kiện mà chỉ có một tiến trình khác trong tập hợp
mới có thể phát sinh được.
Nói cách khác, mỗi tiến trình trong tập hợp đều chờ được cấp phát một tài nguyên hiện
đang bị một tiến trình khác cũng ở trạng thái blocked chiếm giữ. Như vậy không có tiến
trình nào có thể tiếp tục xử lý , cũng như giải phóng tài nguyên cho tiến trình khác sử
dụng, tất cả các tiến trình trong tập hợp đều bị khóa vĩnh viễn !
Vấn đề Bữa ăn tối của các triết gia : 5 nhà triết học cùng ngồi ăn tối với món spaghetti
nổi tiếng. Mỗi nhà triết học cần dùng 2 cái nĩa để có thể ăn spaghetti . Nhưng trên bàn
chỉ có tổng cộng 5 cái nĩa để xen kẽ với 5 cái đĩa. Mỗi nhà triết học sẽ suy ngẫm các triết
lý của mình đến khi cảm thấy đói thì dự định lần lượt cầm 1 cái nĩa bên trái và 1 cái nĩa
bên phải để ăn. Nếu cả 5 nhà triết học đều cầm cái nĩa bên trái cùng lúc, thì sẽ không có
ai có được cái nĩa bên phải để có thể bắt đầu thưởng thức spaghetti . Đây chính là tình
trạng tắc nghẽn.
1/9
Tắc nghẽn (Deadlock)
Hình 3.18 Bữa ăn tối của các triết gia
Điều kiện xuất hiện tắc nghẽn
Coffman, Elphick và Shoshani đã đưa ra 4 điều kiện cần có thể làm xuất hiện tắc nghẽn:
Có sử dụng tài nguyên không thể chia sẻ (Mutual exclusion): Mỗi thời điểm, một tài
nguyên không thể chia sẻ được hệ thống cấp phát chỉ cho một tiến trình , khi tiến trình
sử dụng xong tài nguyên này, hệ thống mới thu hồi và cấp phát tài nguyên cho tiến trình
khác.
Sự chiếm giữ và yêu cầu thêm tài nguyên (Wait for): Các tiến trình tiếp tục chiếm giữ
các tài nguyên đã cấp phát cho nó trong khi chờ được cấp phát thêm một số tài nguyên
mới.
Không thu hồi tài nguyên từ tiến trình đang giữ chúng (No preemption): Tài nguyên
không thể được thu hồi từ tiến trình đang chiếm giữ chúng trước khi tiến trình này sủ
dụng chúng xong.
Tồn tại một chu kỳ trong đồ thị cấp phát tài nguyên ( Circular wait): có ít nhất hai tiến
trình chờ đợi lẫn nhau : tiến trình này chờ được cấp phát tài nguyên đang bị tiến trình
kia chiếm giữ và ngược lại.
Khi có đủ 4 điều kiện này, thì tắc nghẽn xảy ra. Nếu thiếu một trong 4 điều kiện trên thì
không có tắc nghẽn.
Đồ thị cấp phát tài nguyên
Có thể sử dụng một đồ thị để mô hình hóa việc cấp phát tài nguyên. Đồ thị này có 2 loại
nút : các tiến trình được biễu diễn bằng hình tròn, và mỗi tài nguyên được hiển thị bằng
hình vuông
2/9
Tắc nghẽn (Deadlock)
Hình 3.19 Đồ thị cấp phát tài nguyên
Các phương pháp xử lý tắc nghẽn
Chủ yếu có ba hương tiếp cận để xử lý tắc nghẽn :
Sử dụng một nghi thức (protocol) để bảo đảm rằng hệ thống không bao giờ xảy ra tắc
nghẽn.
Cho phép xảy ra tắc nghẽn và tìm cách sữa chữa tắc nghẽn.
Hoàn toàn bỏ qua việc xử lý tắc nghẽn, xem như hệ thống không bao giờ xảy ra tắc
nghẽn.
Ngăn chặn tắc nghẽn
Để tắc nghẽn không xảy ra, cần bảo đảm tối thiểu một trong 4 điều kiện cần không xảy
ra:
Tài nguyên không thể chia sẻ : nhìn chung gần như không thể tránh được điều kiện này
vì bản chất tài nguyên gần như cố định. Tuy nhiên đối với một số tài nguyên về kết xuất,
người ta có thể dùng các cơ chế spooling để biến đổi thành tài nguyên có thể chia sẻ.
Sự chiếm giữ và yêu cầu thêm tài nguyên: phải bảo đảm rằng mỗi khi tiến trình yêu cầu
thêm một tài nguyên thì nó không chiếm giữ các tài nguyên khác. Có thể áp đặt một
trong hai cơ chế truy xuất sau :
Tiến trình phải yêu cầu tất cả các tài nguyên cần thiết trước khi bắt đầu xử lý .
3/9
Tắc nghẽn (Deadlock)
=> phương pháp này có khó khăn là tiến trình khó có thể ước lượng chính xác tài nguyên
cần sử dụng vì có thể nhu cầu phụ thuộc vào quá trình xử lý . Ngoài ra nếu tiến trình
chiếm giữ sẵn các tài nguyên chưa cần sử dụng ngay thì việc sử dụng tài nguyên sẽ kém
hiệu quả.
Khi tiến trình yêu cầu một tài nguyên mới và bị từ chối, nó phải giải phóng các tài
nguyên đang chiếm giữ , sau đó lại được cấp phát trở lại cùng lần với tài nguyên mới.
=> phương pháp này làm phát sinh các khó khăn trong việc bảo vệ tính toàn vẹn dữ liệu
của hệ thống.
Không thu hồi tài nguyên: cho phép hệ thống được thu hồi tài nguyên từ các tiến trình
bị khoá và cấp phát trở lại cho tiến trình khi nó thoát khỏi tình trạng bị khóa. Tuy nhiên
với một số loại tài nguyên, việc thu hồi sẽ rất khó khăn vì vi phạm sự toàn vẹn dữ liệu .
Tồn tại một chu kỳ: tránh tạo chu kỳ trong đồ thị bằng cách cấp phát tài nguyên theo
một sự phân cấp như sau :
gọi R = {R1, R2,...,Rm} là tập các loại tài nguyên.
Các loại tài nguyên được phân cấp từ 1-N.
Ví dụ : F(đĩa) = 2, F(máy in) = 12
Các tiến trình khi yêu cầu tài nguyên phải tuân thủ quy định : khi tiến trình đang chiếm
giữ tài nguyên Ri thì chỉ có thể yêu cầu các tài nguyên Rj nếu F(Rj) > F(Ri).
Tránh tắc nghẽn
Ngăn cản tắc nghẽn là một mối bận tâm lớn khi sử dụng tài nguyên. Tránh tắc nghẽn
là loại bỏ tất cả các cơ hội có thể dẫn đến tắc nghẽn trong tương lai. Cần phải sử dụng
những cơ chế phức tạp để thực hiện ý định này.
Một số khái niệm cơ sở
Trạng thái an toàn : trạng thái A là an toàn nếu hệ thống có thể thỏa mãn các nhu cầu
tài nguyên (cho đến tối đa) của mỗi tiến trình theo một thứ tự nào đó mà vẫn ngăn chặn
được tắc nghẽn.
Một chuỗi cấp phát an toàn: một thứ tự của các tiến trình <P1, P2,...,Pn> là an toàn đối
với tình trạng cấp phát hiện hành nếu với mỗi tiến trình Pi nhu cầu tài nguyên của Pi có
thể được thỏa mãn với các tài nguyên còn tự do của hệ thống, cộng với các tài nguyên
đang bị chiếm giữ bởi các tiến trình Pj khác, với j
4/9
Tắc nghẽn (Deadlock)
Một trạng thái an toàn không thể là trạng thái tắc nghẽn. Ngược lại một trạng thái không
an toàn có thể dẫn đến tình trạng tắc nghẽn.
Chiến lược cấp phát : chỉ thỏa mãn yêu cầu tài nguyên của tiến trình khi trạng thái kết
quả là an toàn!
Giải thuật xác định trạng thái an toàn
Cần sử dụng các cấu trúc dữ liệu sau :
int Available[NumResources];
/* Available[r]= số lượng các thể hiện còn tự do của tài nguyên r*/
int Max[NumProcs, NumResources];
/*Max[p,r]= nhu cầu tối đa của tiến trình p về tài nguyên r*/
int Allocation[NumProcs, NumResources];
/* Allocation[p,r] = số lượng tài nguyên r thực sự cấp phát cho p*/
int Need[NumProcs, NumResources];
/* Need[p,r] = Max[p,r] - Allocation[p,r]*/
1.Giả sử có các mảng
int Work[NumProcs, NumResources] = Available;
int Finish[NumProcs] = false;
2.Tìm i sao cho
Finish[i] == false
Need[i] <= Work[i]
Nếu không có i như thế, đến bước 4.
3. Work = Work + Allocation[i];
Finish[i] = true;
5/9
Tắc nghẽn (Deadlock)
Đến bước 2
4.Nếu Finish[i] == true với mọi i, thì hệ thống ở trạng thái an toàn.
Ví dụ : Giả sử tình trạng hiện hành của hệ thống được mô tả như sau :
Max Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
P1
3
2
2
1
0
0
P2
6
1
3
2
1
1
P3
3
1
4
2
1
1
P4
4
2
2
0
0
2
Nếu tiến trình P2 yêu cầu 4 cho R1, 1 cho R3. hãy cho biết yêu cầu này có thể đáp ứng
mà bảo đảm không xảy ra tình trạng deadlock hay không ? Nhận thấy Available[1] =4,
Available[3] =2 đủ để thõa mãn yêu cầu của P2, ta có
Need Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
P1
2
2
2
1
0
0
P2
0
0
1
6
1
2
P3
1
0
3
2
1
1
P4
4
2
0
0
0
2
Need Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
P1
2
2
2
1
0
0
P2
0
0
0
0
0
0
P3
1
0
3
2
1
1
P4
4
2
0
0
0
2
Need Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
6/9
Tắc nghẽn (Deadlock)
P1
0
0
0
0
0
0
P2
0
0
0
0
0
0
P3
1
0
3
2
1
1
P4
4
2
0
0
0
2
Need Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
P1
0
0
0
0
0
0
P2
0
0
0
0
0
0
P3
0
0
0
0
0
0
P4
4
2
0
0
0
2
Need Allocation Available
R1
R2
R3
R1 R2 R3 R1 R2 R3
P1
0
0
0
0
0
0
P2
0
0
0
0
0
0
P3
0
0
0
0
0
0
P4
0
0
0
0
0
0
Trạng thái kết qủa là an toàn, có thể cấp phát.
Giải thuật yêu cầu tài nguyên
Giả sử tiến trình Pi yêu cầu k thể hiện của tài nguyên r.
1.Nếu k <= Need[i], đến bước 2
Ngược lại, xảy ra tình huống lỗi
2.Nếu k <= Available[i],đến bước 3
Ngược lại, Pi phải chờ
3.Giả sử hệ thống đã cấp phát cho Pi các tài nguyên mà nó yêu cầu và cập nhật tình trạng
hệ thống như sau:
Available[i] = Available[i] - k; Allocation[i]= Allocation[i]+ k; Need[i] = Need[i] - k;
7/9
Tắc nghẽn (Deadlock)
Nếu trạng thái kết quả là an toàn, lúc này các tài nguyên trên sẽ được cấp phát thật sự
cho Pi
Ngược lại, Pi phải chờ
Phát hiện tắc nghẽn
Cần sử dụng các cấu trúc dữ liệu sau :
int Available[NumResources];
// Available[r]= số lượng các thể hiện còn tự do của tài nguyên r
int Allocation[NumProcs, NumResources];
// Allocation[p,r] = số lượng tài nguyên r thực sự cấp phát cho p
int Request[NumProcs, NumResources];
// Request[p,r] = số lượng tài nguyên r tiến trình p yêu cầu thêm
Giải thuật phát hiện tắc nghẽn
1. int Work[NumResources] = Available;
int Finish[NumProcs];
for (i = 0; i < NumProcs; i++)
Finish[i] = (Allocation[i] == 0);
2. Tìm i sao cho
Finish[i] == false
Request[i] <= Work
Nếu không có i như thế, đến bước 4.
3. Work = Work + Allocation[i];
Finish[i] = true;
Đến bước 2
8/9
Tắc nghẽn (Deadlock)
4. Nếu Finish[i] == true với mọi i,
thì hệ thống không có tắc nghẽn
Nếu Finish[i] == false với một số giá trị i,
thì các tiến trình mà Finish[i] == false sẽ ở trong
tình trạng tắc nghẽn.
Hiệu chỉnh tắc nghẽn
Khi đã phát hiện được tắc nghẽn, có hai lựa chọn chính để hiệu chỉnh tắc nghẽn :
Đình chỉ hoạt động của các tiến trình liên quan
Cách tiếp cận này dựa trên việc thu hồi lại các tài nguyên của những tiến trình bị kết
thúc. Có thể sử dụng một trong hai phương pháp sau :
-Đình chỉ tất cả các tiến trình trong tình trạng tắc nghẽn
-Đình chỉ từng tiến trình liên quan cho đến khi không còn chu trình gây tắc nghẽn : để
chọn được tiến trình thích hợp bị đình chỉ, phải dựa vào các yếu tố như độ ưu tiên, thời
gian đã xử lý, số lượng tài nguyên đang chiếm giữ , số lượng tài nguyên yêu cầu...
Thu hồi tài nguyên
Có thể hiệu chỉnh tắc nghẽn bằng cách thu hồi một số tài nguyên từ các tiến trình và cấp
phát các tài nguyên này cho những tiến trình khác cho đến khi loại bỏ được chu trình tắc
nghẽn. Cần giải quyết 3 vấn đề sau:
-Chọn lựa một nạn nhân: tiến trình nào sẽ bị thu hồi tài nguyên ? và thu hồi những tài
nguyên nào ?
-Trở lại trạng thái trước tắc nghẽn: khi thu hồi tài nguyên của một tiến trình, cần phải
phục hồi trạng thái của tiến trình trở lại trạng thái gần nhất trước đó mà không xảy ra tắc
nghẽn.
-Tình trạng « đói tài nguyên »: làm sao bảo đảm rằng không có một tiến trình luôn luôn
bị thu hồi tài nguyên ?
9/9