HỌC VIỆN KỸ THUẬT MẬT MÃKHOA CỒNG NGHỆ THÔNG TIN BÀI TẬP MÔN HỌC NGUYÊN LÝ HỆ ĐIỀU HÀNH VIẾT CHƯƠNG TRÌNH MÔ PHỎNG QUÁ TRÌNH ĐỒNG BỘ TIẾN TRÌNH THEO THEO THUẬT TOÁN 5 TRIẾT GIA ĂN TỐI BẰ
Trang 1HỌC VIỆN KỸ THUẬT MẬT MÃ
KHOA CỒNG NGHỆ THÔNG TIN
BÀI TẬP MÔN HỌC NGUYÊN LÝ HỆ ĐIỀU HÀNH
VIẾT CHƯƠNG TRÌNH MÔ PHỎNG QUÁ TRÌNH ĐỒNG BỘ TIẾN TRÌNH THEO THEO THUẬT TOÁN 5 TRIẾT GIA ĂN TỐI BẰNG
NGÔN NGỮ JAVA
Ngành: An toàn thông tin
Sinh viên thực hiện:
Nguyễn Văn Hiệp
Phạm Công Hưởng
Nguyễn Anh Tuấn
Lớp: AT16C0405
Người hướng dẫn:
TS Nguyễn Đào Trường
Khoa Công nghệ thông tin - Học viện Kỹ thuật mật mã
Trang 2Hà Nội, 2022
Trang 3NHẬN XÉT VÀ CHO ĐIỂM CỦA GIÁO VIÊN
Trang 4LỜI NÓI ĐẦU
Nếu không có phần mềm, máy tính chỉ là một thiết bị điện tử thông thường Với sự hỗ trợ của phần mềm, máy tính có thể lưu trữ, xử lý thông tin và người sử dụng có thể gọi lại được thông tin này Phần mềm máy tính có thể chia thành nhiều loại: chương trình hệ thống, quản lý sự hoạt động của máy tính Chương trình ứng dụng, giải quyết các vấn đề liên quan đến việc sử dụng và khai thác máy tính của người sử dụng hệ điều hành thuộc nhóm các chương trình hệ thống và nó là một chương trình hệ thống quan trọng nhất đối với máy tính và cả người sử dụng Hệ điều hành điều khiển tất cả các tài nguyên của máy tính và cung cấp một môi trường
thuận lợi để các chương trình ứng dụng do người sử dụng viết ra có thể chạy được trên máy tính
Một máy tinh hiện đại có thể bao gồm: một hoặc nhiều processor, bộ nhớ, clocks, đĩa, giao diện mạng, và các thiết bị vào/ra khác Tất cả nó tạo thành một hệ thống phức tạp Để viết các chương trình để theo dõi tất cả các thành phần của máy tính và sử dụng chúng một cách hiệu quả, người lập trình phải biết processor thực hiện chương trình như thế nào, bộ nhớ lưu trữ thông tin như thế nào, các thiết bị đĩa làm việc (đọc/ghi) như thế nào, lỗi nào có thể xảy ra khi đọc một block đĩa, đây
là những công việc rất khó khăn và quá quá khó đối với người lập trình Nhưng rất may cho cả người lập trình ứng dụng và người sử dụng là những công việc trên đã được hệ điều hành hỗ trợ nên họ không cần quan tâm đến cái đấy nữa Chúng ta cần tìm hiểu về hệ điều hành đề có một cái nhìn tổng quát về những gì liên quan đến việc
thiết kế cài đặt cũgn như chức năng của hệ điều hành để hệ điều hành đạt được mục tiêu: Giúp người sử dụng khai thác máy tính một cách dễ dàng và chương trình của người sử dụng có thể chạy được trên máy tính
“Bài toán bữa tối của các triết gia” (Dining Philosophers), một bài toán kinh điển về tương tranh và chia sẻ tài nguyên Việc nghiên cứu bài toán sẽ cho chúng ta hiểu rõ hơn về khia cạnh này của hệ thống
Trang 5CHƯƠNG 1: CƠ SỞ LÝ THUYẾT
I, Tiến trình(processes)
1, Khái niệm:
- Tiến trình là một bộ phận của một chương trình thực đang thực hiện, đơn vị thực hiện tiến trình là processer
- Vì tiến trình là một bộ phận của chương trình nên tương tự như chương
trình tiến trình cũng sở hữu một con trỏ lệnh, một con trỏ stack, một tập các thanh ghi, một không gian địa chỉ trong bộ nhớ chính và tất cả các thông tin cần thiết khác
để tiến trình có thể hoạt động được
2, Các loại tiến trình:
- Các tiến trình trong hệ thống chia làm hai loại: tiến trình tuần tự và tiến trình song song
+ Tiến trình tuần tự là các tiến trình mà điểm khởi tạo của nó là điểm kết thúc của tiến trình trước đó
+ Tiến trình song song là các tiến trình mà điểm khởi tạo của tiến
trình này nằm ở thân của các tiến trình khác, thức là có thể khởi tạo một tiến trình mới khi các tiến trình đó chưa kết thúc
II, Luồng(Thread)
Luồng là thành phần của tiến trình sở hữu ngăn xếp và thực thi độc lập ngay trong mã lệnh của tiến trình Nếu như hệ điều hành có nhiều tiến trình thì trong mỗi tiến trình bạn có thể tạo ra nhiều tuyến hoạt động song song trong hệ điều hành Ưu điểm của tuyến là chúng hoạt động trong cùng một không gian địa chỉ của tiến trình
Tập hợp một nhóm các tuyến có thể sử dụng chung biến toàn cục, vùng nhớ Heap, bảng mô tả íìle của tiến trình, cơ chế liên lạc giữa tuyến đơn giản và hiệu quả hơn
cơ chế liên lạc giữa các tiến trình với nhau
Ưu điểm của việc sử dụng luồng trong tiến trìnhh đơn giản hơn lập trình tuần
tự Nhiều thao tác xuất nhập hoặc hiển thị dữ liệu có thể tách rời và phân cho các tuyến chạy độc lập thực thi
III, Giải pháp Semaphore
Semaphore là một dóng góp quan trọng của nhà toán học E W Dijktra Có
Trang 6thể xem Semaphore như là một mở rộng của Mutex locks.
Semaphore S là một biến tài nguyên, khởi gán bằng một giá trị không âm, đó
là khả năng phục vụ của tài nguyên tương ứng với nó
Ứng với S có một hàng đợi F(s) để lưu các tiến trình đang bị blocked trên S
Trang 7Chỉ có hai thao tác Down và Up được tác động đến Semaphore S Down giảm
S xuống một đơn vị, Up tăng S lên một đơn vị
Ở đây chúng ta cần lưu ý rằng: Down và Up là các thủ tục của hệ điều hành, nên hệ điều hành đã cài đặt cơ chế độc quyền cho nó, tức là các lệnh bên trong nó không thể tách rời nhau
IV, Deadlock
- Deadlock là một trạng thái mà ở đó một tập các tiến trình bị chặn vì mỗi tiến
trình đang chiếm giữ tài nguyên và chờ đợi được cấp phát tài nguyên khác được giữ bởi tiến trình khác Nói cách khác, mỗi tiến trình trong hệ thống đang chờ để được cấp phát tài nguyên đang bị chiếm giữ bởi tài nguyên khác Nếu tài nguyên đó không
được giải phóng để tiến trình khác có thể sử dụng, thì tiến trình đang chờ lấy tài nguyên sẽ chờ mãi, chờ mãi dẫn đến khoá chết (Deadlock)
- Các điều kiện phát sinh Deadlock:
+ Loại từ tương hỗ (Mutual Exclusion): tại một thời điểm, tài nguyên không thể chia sẻ được cho hệ thống cấp phát cho một tiến trình duy nhất Tiến trình
khác không thể sử dụng cho đến khi tài nguyên được giải phóng
+ Giữ và chờ (hold and wait): Mỗi tiến trình trong tập hợp tiến trình đang giữ một tài nguyên và chờ đợi để được cấp phát một tài nguyên mới
+ Không có quyền ưu tiên (No Preemption): Một tiến trình không thể ciếm giữ tài nguyên cho đến khi tài nguyên đó được giải phóng bởi tiến trình đang
sử dụng nó
+ Tồn tại chu kì chờ (Circular Wait): Các tiến trình giữ một tài nguyên
và chờ nhận một tài nguyên khác bởi tiến trình kahsc Chúng nối đuôi nhau tạo thành
vòng tròn Chờ vô tận
Trang 8CHƯƠNG 2: MÔ TẢ BÀI TOÁN
I, Đề bài:
Viết chương trình mô phỏng quá trình đồng bộ tiến trình (điều độ) theo thuật toán 5 triết gia ăn tối bằng ngôn ngữ Java
II, Mô tả bài toán:
Đây là một bài toán cổ điển về hệ điều hành Bài toán bữa tối của các triết gia đưuocj đưa ra bời nhà toán học E W.Dijkstra Bài toán được mô tả như sau: Có năm
triết gia cùng ngồi ăn quanh một chiếc bàn tròn, trước mặt mỗi người có một đĩa đồ
ăn, mỗi người có một đĩa, giữa hai triết gia thì có một chiếc đũa Bài toán được phát biểu như sau: “ khi một triết gia suy nghĩ, ông ta không thể giao tiếp với các triết gia
khác Thỉnh thoảng, một triết gia cảm thấy đói và cố gắng chọn 2 chiếc đũa gần nhất(
đũa trái và đũa phải) Một triết gia chỉ có thể chỉ lấy một chiếc đũa tại một thời điểm
Chú ý, ông ta không thể lấy chiếc đũa mà nó đang được dùng bởi người bên cạnh Khi một triết gia đối và có hai chiếc đũa cùng một lúc, ông ta ăn mà không đặt đũa
xuống Khi triết gia ăn xong, ông ta đặt đũa xuống và bắt đầu suy nghĩ tiếp”.
III, Yêu cầu:
- Tìm cách để không ai chết đói
- Bài toán đặt ra vấn đề “đồng bộ giữa các tiến trình”, giải quyết vấn đề tắc nghẽn có thể xảy ra
Trang 9CHƯƠNG 3: CÁCH GIẢI QUYẾT BÀI TOÁN
I, Mô tả hướng giải quyết
Để giải quyết bài toán, thì trong phần này, ta sẽ sử dụng thuật toán Semaphore
Và sử dụng tính chất hoạt động song song của đa luồng (Thread)
II, Giải thích code và kết quả
1, Class Fork (đũa):
statĩc class Fork {
public Semaphore mutex = new Semaphữ
void grab() {
mutex acquire()j
}
catch (Exception e) {
e.printStackTrace(Syst em.out) ;
}
}
void release() {
mutex release()■
}
boolean isFree() {
return mutex.availablePermitsO > 0j
}
}
- Với class này, chúng ta áp dụng thuật toán Semaphore để đánh dấu trạng thái của những chiếc đũa trong bài toán Những chiếc đũa ban đầu sẽ có giá trị là 1 Ở giá trị này, thì nó coi là đang không được sử dụng
- Khi mà chiếc đũa đang được sử dụng, với phương thức acquire(), sẽ gán cho chiếc
đũa đấy giá trị là 0 - hay là đang trong trạng thái sử dụng
- Khi mà sử dụng xong (Hết sleep time) thì phương thức release() sẽ trả lại cho chiếc
đũa đấy giá trị là 1
- Ở đây, ta sẽ cho thêm phương thức isFree(), phương thức này sẽ giúp kiểm tra
Trang 10thái của chiếc đũa
2, Class Philosopher
Trang 11static class Philosopher extends Thread {
public int number;
public Fork leftFork;
public Fork rightFork;
Philosopher(int num, Fork left, Fork right) {
number = num;
leftFork = leít;
rightFork = right;
}
public void run(){
System.out println("Xin chão! Tòi lã nhã triết gia số " + number);
int think = 0;
while (true) {
lef tFor k grab ( ;
System out.println("Nhà triểt gia số " + number + ” láy đũa trái 1 ');
rightFork grab( ;
System out.println("Nhà triết gia sổ " + number + " láy đũa phải.");
think = 1;
eat();
leftFork release();
System out.println("Nhà triết gia số " + number + " nhả đũa trái.");
rightFork release();
System out.println("Nhà triết gia số " + number + " nhả đũa phải.");
if (think == 1) 0
System.out println("Nhà triết gia sổ " + number + " đang suy nghĩ! 1 '); }|
}
}
//
void eat() {
try {
int sleepTime = ThreadLocalRandom.currento.nextlnt(0, 1000);
System out.println("Nhà triết gia số " + number + " ăn trong " + sleepTime);
Thread.steep(sleepTime);
}
catch (Exception e) {
e printStackTrace ( System.out);
}
1
- Với class Philosopher, ta sẽ kế thừa class Thread để giúp cho class này sử dụng cơ
chế đa luồng của Thread
- Đầu tiên, sẽ có 3 thuộc tính, đó là number: số thứ tự của các nhà triết gia,
leftFork
và rightFork: là đũa trái, đũa phải của các triết gia tương ứng
- Tiếp theo, sẽ có một hàm khởi tạo của class này
- Các triết gia có các hành động là: tham gia vào bữa ăn, lấy đũa trái, lấy đũa phải, suy nghĩ và ăn
3, Main:
Trang 12public static void main(string argv[]) {
System.out println("Giái quyết vãn đề bữa ăn của các nhà triết gia.");
for (int i = 0; i < phỉLosophersNumber; i++) {
/orfes[i] = new Fork();
for (int i = 0; i < phiLosophersNumber' Ỉ++) {
phỉLosophers[i] = new Philosopheríi, /orfes[i]j forks[(i + 1) %
phỉLosophersNumber]) ;
phỉLosophers[i].start();
}
while (true) {
try {
// sleep 1 séc
Thread.steep(1000);
// check for deadlock
boolean deadlock = true;
for (Fork f : forks) {
if (f.isFree()) {
deadlock = talse;
break;
} '
}
if (deadlock) {
Thread.steep(1000);
System out println("cảnh báo! Đã đẽn giới hạn Deadlock!");
break;
}
}
catch (Exception e) {
e printStackTrace(System out);
}
}
System.out println("Bye!");
System.exit(0);
}
- Phương thức Main, là phương thức sẽ sử dụng hai class mà đã tạo là class Fork và class Philosopher để chạy chương trình
|for (int i = 0; i < phiLosophersNuíìỉber; i++) {
/orks[i] = new Fork()j
}
- Dùng để tạo một mảng chứa các đối tượng đũa
|for (int i = 0; ỉ < phiLosophersNumber; i++) {
phitosophers[i] = new Philosopher(i, yorfes[i]j forks[(i + 1) % phiLosophersNumber]) ;
phiLosophers[i].start();
}
Dùng để tạo mảng gán các đối tượng nhà triết gia và khởi động luồng
Trang 13uhile (true) {
try {
/Ị sleep 1 sec
Thread.sLeep(1000);
Ị ị check for deadlock
bũũlean deadlock = truej
for (Fork f : /ơrks) {
if (í.isFree()) {
break;
}
}
Thread.steep(1000);
System out.printỉn ("Cảnh báo! Đã đến giới hạn Deadlock!")j
break;
}
}
catch (Exception e) {
e.prĩntStackTrace(System.out);
}
}
System out println( "Bye !");
System.exit(0);
}
- Với vòng lặp While, vòng lặp này sẽ có tác dụng kiểm tra quá trình Deadlock Tất
cả các luồng được kiểm tra về tài nguyên đang được chiếm giữ Nếu như tất cả các luồng bị quá tải do không đủ tài nguyên, dẫn đến giới hạn của Deadlock, người dùng
sẽ nhận một cảnh báo và tự động dừng chương trình
Trang 14KẾT LUẬN
Qua bài tập này, chúng ta sẽ hiểu rõ hơn về cách thức hoạt động của luồng trong hệ điều hành, cách các luồng nhận và giả lại tài nguyên sao cho hợp lý để cho
hệ điều hành hoạt động tốt nhất có thể Và hiểu thêm về thuật toán Semaphore và cách thức hoạt động của nó, kết hợp với luồng, để có thể sử dụng trong một trường hợp nào đấy trong tương lai Em cảm ơn thầy đã cho em cơ hội được nghiên cứu về
đề tài này và giúp em có thêm kiến thức Em xin cảm ơn!