- Đọ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.