- Đọc/Ghi ngày, tháng, năm
a) Sử dụng lệnh SLEEP VÀ WAKEUP
Hệ điều hành cung cấp hai lệnh SLEEP VÀ WAKEUP. Nếu tiến trình gọi lệnh SLEEP, hệ điều hành sẽ chuyển tiến trình sang “danh sách sẵn sàng”, lấy lại CPU cấp cho tiến trình khác. Nếu tiến trình gọi lệnh WAKEUP, hệ điều hành sẽ chọn một tiến trình trong ready list, cho thực hiện tiếp. Khi một tiến trình chƣa đủ điều kiện vào miền găng, nĩ gọi SLEEP để tự khĩa, đến khi cĩ một tiến trình khác gọi WAKEUP để giải phĩng cho nĩ. Một tiến trình gọi WAKEUP khi ra khỏi miền găng để đánh thức một tiến trình đang chờ, tạo cơ hội cho tiến trình này vào miền găng. Việc sử dụng hai lệnh SLEEP VÀ WAKEUP thực khơng đơn giản, rất dễ bị lỗi. Thực vậy, ta xét một chƣơng trình giải quyết bài tốn miền găng nhƣ sau:
//busy và blocked là hai biến dùng chung.
int busy=FALSE; // TRUE là cĩ tiến trình trong miền găng, FALSE là khơng cĩ tiến trình trong miền găng.
int blocked=0; // đếm số lƣợng tiến trình đang bị khĩa while (TRUE) //để cho một tiến trình cĩ thể vào mg nhiều lần { if (busy) { blocked = blocked + 1; sleep(); }
else busy = TRUE; critical-section (); busy = FALSE; if (blocked>0) {
wakeup(); //đánh thức một tiến trình đang chờ blocked = blocked - 1;
}
Noncritical-section (); }
Nhận xét:
- Cĩ thể vi phạm điều kiện thứ 1 là cĩ hai tiến trình trong miền găng cùng lúc. Thực vậy, giả sử tiến trình A kiểm tra biến busy, thấy busy=FALSE, nhƣng chƣa kịp gán busy=TRUE thì đến lƣợt tiến trình B. B thấy busy=FALSE, B gán busy=TRUE và vào miền găng. Trong khi B chƣa ra khỏi miền găng thì đến lƣợt A, A gán busy=TRUE và vào miền găng!
- Cĩ thể vi phạm điều kiện thứ ba là một tiến trình cĩ thể bị ngăn chặn vào miền găng bởi một tiến trình khác khơng ở trong miền găng. Ví dụ giả sử tiến trình A vào miền găng, và trƣớc khi nĩ rời khỏi miền găng thì tiến trình B đƣợc kích hoạt. Tiến trình B thử vào miền găng nhƣng nĩ nhận
thấy A đang ở trong đĩ, do vậy B tăng giá trị biến blocked và chuẩn bị gọi SLEEP để tự khố. Tuy nhiên trƣớc khi B cĩ thể thực hiện SLEEP, tiến trình A lại đƣợc tái kích hoạt và ra khỏi miền găng. Khi ra khỏi miền găng A nhận thấy cĩ một tiến trình đang chờ (blocked=1) nên gọi WAKEUP và giảm giá trị của blocked. Khi đĩ tín hiệu WAKEUP sẽ lạc mất do tiến trình B chƣa thật sự “ ngủ “ để nhận tín hiệu đánh thức ! Khi tiến trình B đƣợc tiếp tục xử lý, nĩ mới goi SLEEP và tự ngủ vĩnh viễn !
Lỗi này xảy ra do việc kiểm tra biến busy và việc gọi SLEEP là những hành động tách biệt, cĩ thể bị ngắt giữa chừng trong quá trình xử lý. Để tránh những tình huống tƣơng tự, hệ điều hành cung cấp những cơ chế đồng bộ hĩa nhƣ Semaphore, Monitor dựa trên ý tƣởng của chiến lƣợc “SLEEP and WAKEUP” nhƣng việc kiểm tra điều kiện vào miền găng và việc chờ xây dựng thành một hành động độc quyền, giúp việc giải quyết bài tốn miền găng an tồn, hiệu qủa hơn.