Tải bản đầy đủ (.doc) (14 trang)

VẤN ĐỀ DEADLOCK TRONG JAVA ĐỒ ÁN MÔN:NGUYÊN LÝ HỆ ĐIỀU HÀNH

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (286.06 KB, 14 trang )

BAN CƠ YẾU CHÍNH PHỦ
HỌC VIỆN KỸ THUẬT MẬT MÃ
KHOA: AN TOÀN THÔNG TIN

NGUYÊN LÝ HỆ ĐIỀU HÀNH

VẤN ĐỀ DEADLOCK TRONG JAVA

Giảng viên hướng dẫn:
Sinh viên thực hiện:

Lớp: AT13N03

Ths. Trần Văn Minh
Nguyễn Xuân Anh Thư
Nguyễn Trịnh Phương Linh
Nguyễn Xuân Thiên
Trần Ngọc Thanh Vy
Trần Thảo Vy


LỜI MỞ ĐẦU
Đề tài được nghiên cứu thông qua quá trình tìm hiểu các tài liệu về “Vấn đề Deadlock trong
Java”. Từ đó đưa ra những phương pháp, các biện pháp khắc phục cũng như ngăn chặn quá trình
xảy ra Deadlock. Giúp giảm thiểu chi phí và thời gian xây dựng hệ thống.
Đề tài được chia làm 4 chương:
Chương 1: Deadlock
Chương 2: Vấn đề Deadlock trong Java
Chương 3: Chương trình minh họa vấn đề Deadlock trong Java
Chương 4: Kết luận


2


CHƯƠNG 1: DEADLOCK
1.1

Deadlock là gì? Tại sao lại xảy ra Deadlock?
-

Một tiến trình gọi là deadlocked nếu nó đang đợi một sự kiện mà sẽ không bao giờ xảy
ra. Thông thường, có nhiều hơn một tiến trình bị liên quan trong một deadlock.

-

Deadlock (Tắc nghẽn) là trạng thái xảy ra trong môi trường đa nhiệm (muti-threading)
khi hai hoặc nhiều tiến trình đi vào vòng lặp chờ tài nguyên mãi mãi.
o Ví dụ: Khi có thread (1) đang giữ tài nguyên (A) và cần truy cập tài nguyên(B) để

tiếp tục xử lý (call method xử lý…) nhưng tài nguyên (B) đang được thread (2) sử
dụng, trong lúc này thì thread (2) cũng đang cần truy cập vào tài nguyên (A) mà
thread (1) đang sử dụng. Lúc này thì cả 2 thread đều không thể tiếp tục thực hiện mà
đều phải “chờ” nhau nhưng không biết khi nào thì sẽ kết thúc.
-

Một tiến trình gọi là trì hoãn vô hạn định (Indefinitely postponed) nếu nó bị trì hoãn một
khoảng thời gian dài lặp đi, lặp lại trong khi hệ thống đáp án cho những tiến trình khác.

1.2

o Ví dụ: Một tiến trình sẵn sàng để xử lý nhưng nó không bao giờ nhận được CPU.

Điều kiện cần để xảy ra DeadLock?
-

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:
1) Loại trừ hỗ tương (Mutual exclusion): có sử dụng tài nguyên không thể chia sẻ
(nonsharable).
• 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. (Ví dụ: printer; shareable resource: readonly files).
2) Giữ và chờ cấp thêm tài nguyên (Hold and Wait): một process đang tiếp tục chiếm giữ
ít nhất một tài nguyên và đang chờ thêm tài nguyên do quá trình khác đang giữ.
3) Không trưng dụng (Nopreemption): 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.
4) Chu trình đợi (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.

 Ví dụ: tồn tại một tập {A1 ,A2,…An} các quá trình đang đợi sao cho
3


A1 đợi một tài nguyên của A2 đang giữ
A2 đợi một tài nguyên của A3 đang giữ
A(n) đợi một tài nguyên của A1 đang giữ
 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.

1.3 Làm thế nào để phát hiện ra Deadlock?
-


Chấp nhận xảy ra deadlock trong hệ thống, kiểm tra trạng thái hệ thống bằng giải thuật
phát hiện deadlock.

-

Nếu có deadlock thì tiến hành phục hồi hệ thống

-

Các giải thuật phát hiện deadlock thường sử dụng mô hình RAG

-

Hệ thống cấp phát tài nguyên được khảo sát trong một số trường hợp sau:

o Mỗi loại tài nguyên chỉ có một thực thể (instance).
o Mỗi loại tài nguyên có thể có nhiều thực thể.
1.4 Các biện pháp để ngăn chặn Deadlock?
-

Ngăn deadlock bằng cách ngăn một trong 4 điều kiện cần để xảy ra deadlock
1) Ngăn Mutual Exclusion:

o Đối với Nonsharable resource (ví dụ: printer): không làm được
o Đối với Sharable resource (ví dụ: read-only files): không cần thiết.
2) Ngăn Hold and Wait:

o Cách 1: Mỗi process yêu cầu toàn bộ tài nguyên cần thiết một lần. Nếu có đủ tài
nguyên thì hệ thống sẽ cấp phát, nếu không đủ tài nguyên thì process phải bị
blocked.


o Cách 2: Khi yêu cầu tài nguyên, process không được giữ bất kỳ tài nguyên nào.
Nếu đang có thì phải trả lại trước khi yêu cầu.

o Khuyết điểm của các cách trên:
4


 Hiệu suất sử dụng tài nguyên thấp.
 Qúa trình có thể bị starvation.
3) Ngăn No Preemption: Nếu process A có giữ tài nguyên và đang yêu cầu tài nguyên

khác nhưng tài nguyên này chưa cấp phát ngay được thì:

o Cách 1: Hệ thống lấy lại mọi tài nguyên mà A đang giữ.
 A chỉ bắt đầu lại được khi có được các tài nguyên đã bị lấy lại cùng với tài
nguyên đang yêu cầu.

o Cách 2: Hệ thống sẽ xem tài nguyên mà A yêu cầu.
 Nếu tài nguyên được giữ bởi 1 process khác đang đợi thêm tài nguyên, tài
nguyên này được hệ thống lấy lại và cấp phát cho A.

 Nếu tài nguyên được giữ bởi process không đợi tài nguyên, A phải đợi và
tài nguyên của A bị lấy lại. Tuy nhiên hệ thống chỉ lấy lại các tài nguyên
mà process khác yêu cầu.
4) Ngăn Circular Wait: Gán một thứ tự cho tất cả các tài nguyên trong hệ thống.

1.5 Các biện pháp để tránh deadlock:
-


Deadlock prevention sử dụng tài nguyên không hiệu quả.

-

Deadlock avoidance vẫn đảm bảo hiệu suất sử dụng tài nguyên tối đa đến mức có thể.
Yêu cầu mỗi process khai báo số lượng tài nguyên tối đa cần để thực hiện công việc.

-

Sử dụng giải thuật deadlock-avoidance sẽ kiểm tra trạng thái cấp phát tài nguyên để đảm
bảo hệ thống không rơi vào deadlock.

o Giải thuật đồ thị cấp phát tài nguyên
o Giải thuật Banker
o Giải thuật yêu cầu tài nguyên
o Giải thuật kiểm tra trạng thái an toàn
 Giải thuật đồ thị cấp phát tài nguyên:
a) Ký hiệu:

o Process:
o Loại tài nguyên với 4 thực thể:
5


o Pi yêu cầu một thực thể của Rj:
o Pi đang giữ một thực thể của Rj:
b) Đồ thị cấp phát tài nguyên (Resource Allocation graph – RAG) là đồ thị có hướng với
tập đỉnh V và tập cạnh E.

o Tập đỉnh V gồm 2 loại:

 P = {P1,P2,…,Pn} : Tất cả process trong hệ thống
 R = {R1,R2,…Rm} : Tất cả các loại tài nguyên trong hệ thống
o Tập cạnh E gồm 2 loại:
 Cạnh yêu cầu: Pi -> Rj
 Cạnh cấp phát: Rj -> Pi
c) RAG và deadlock:

o RAG không chứa chu trình => Không xảy ra deadlock

o RAG chứa một hay nhiều chu trình:
 Nếu mỗi loại tài nguyên chỉ có một thực thể => Xảy ra deadlock
 Nếu mỗi loại tài nguyên có nhiều thực thể => có thể xảy ra deadlock

6


1.6 Khi Deadlock xảy ra thì phục phồi Deadlock như thế nào?
-

Chủ yếu có ba hương tiếp cận để xử lý tắc nghẽn khi deadlock xảy ra :
Dùng một giao thức ( protocol ) để ngăn chặn (preventing) hoặc tránh(avoiding)
deadlock , đảm bảo hệ thống không bao giờ rơi vào tình trạng deadlock

1)

Trong đó:
+ Ngăn deadlock (Preventing): không cho phép (ít nhất) một trong 4 điều kiện cần xuất
hiện deadlock
+Tránh deadlock (Avoiding): các process cần cung cấp thông tin về tài nguyên nó cần, để
hệ thống cấp phát tài nguyên một cách thích hợp.

2) Cho phép hệ thống vào trạng thái deadlock , nhưng sau đó phát hiện deadlock và phục hồi
hệ thống
3) Bỏ qua mọi vấn đề , xem như deadlock không bao giờ xảy ra trong hệ thống

o Nhiều hệ điều hành sử dụng phương pháp này. Dẫn đến deadlock không được phát hiện,
làm giảm hiệu suất của hệ thống. Cuối cùng hệ thống ngừng hoạt động và phải được khởi
động lại
-

Khi deadlock xảy ra, để phục hổi thì:

o Báo người vận hành hệ thống
o Hệ thống tự động phục hồi bằng cách bẻ gãy chu trình deadlock:
7


 Chấm dứt một hay nhiều quá trình.
 Lấy lại tài nguyên từ một hay nhiều quá trình.
-

Kết hợp 3 phương pháp cơ bản: Ngăn chặn (Prevention), tránh (avoidance), phát hiện
(detection), cho phép sử dụng cách giải quyết tối ưu cho mỗi lớp tài nguyên trong hệ
thống để giải quyết deadlock.

-

Phân chia tài nguyên thành các lớp theo thứ bậc: Sử dụng kỹ thuật thích hợp nhất cho
việc quản lý deadlock trong mỗi lớp này.

CHƯƠNG 2: DEADLOCK TRONG JAVA

2.1 Deadlock trong Java xảy ra như thế nào?
-

Trong Java, Deadlock là trường hợp có ít nhất hai luồng đang chiếm giữ tài nghuyên
khác nhau, và cả hai luồng đều đang chờ tài nguyên của bên thứ còn lại để hoàn thành
công việc. Và không bên nào chịu giải phòng tài nguyên mà mình đang chiếm giữ.

-

Deadlock xảy ra chúng ta sử dụng synchronization với mục đích đảm bảo thread-safe
nhưng nếu không cẩn thận khi sử dụng lock-object (objectidentifier) thì sẽ dễ dẫn đến
deadlock.

-

Các vấn đề thường gặp trong multithread:

o Hai hay nhiều thread tranh nhau sử dụng chung tài nguyên - race condition.
o Thread này chiếm giữ tài nguyên của thread khác yêu cầu đến -> dẫn đến bị tắc
nghẽn - deadlock.

o Các thread khác chiếm hết tài nguyên -> có thread không được cung cấp đủ tài
nguyên -> đói tài nguyên - resource starvation.

2.2 DeadLock trong Java gồm những trường hợp, sử dụng những phương thức nào?
-

Để tránh các trường hợp thường gặp ở trên, trong Java thường sử dụng:

o Sử dụng cơ chế Monitor.

o Sử dụng cơ chế Semaphore.
o Sử dụng cơ chế synchronized.
o Sử dụng Object Lock.
8


2.3 Phương thức Synchronized:
2.3.1 Synchronized:
-

Từ khoá synchronized được sử dụng cho việc truy cập độc quyền. Để thực hiện một
phương pháp đồng bộ, chỉ cần thêm từ khóa synchronized để khai báo. Sau đó, sẽ không
có hai lời gọi của method đồng bộ trên cùng một đối tượng có thể xen vào với nhau.

-

Synchronized phải xác định đối tượng cung cấp các khóa bên trong. Khi đồng bộ đối
tượng - synchronized object được sử dụng, bạn phải tránh sử dụng đồng bộ hóa method
trên một đối tượng khác cùng tham gia vào method đồng bộ hiện tại.

-

Ta có thể sử dụng sychronization bằng các cách:

o Synchronized method: đặt từ khóa synchronized trong method
o Synchronized block: đặt từ khóa synchronized bên trong method
-

Sự khác nhau giữa Synchronized method và Synchronized block:


o Dùng synchronized method có nghĩa là cả method sẽ bị block bởi 1 thread khi
thread đó thực thi. Cách này đơn giản nhưng đôi lúc hơi cưng nhắc.

o Do đó, nên ưu tiên dùng synchronized block để giảm tối đa đoạn code bị lock,
giảm đến mức thấp nhất tình trạng “thắt nút cổ chai” – tất cả các thread phải
“đứng đợi” ngoài method.
2.3.2 Hoạt động của Synchronized
2.3.2.1 Synchronized method
a) Synchronized instance method

public synchronized void add(int value){
this.count += value;
}

-

Chúng ta cần sử dụng từ khóa synchronized trong việc khai báo method. Điều này
cho Java hiểu rằng đây là một synchronized method.

9


-

Một synchronized instance method trong Java được đồng bộ trên instance (object) sở
hữu method đó. Như vậy, mỗi instance có các synchronized method được đồng bộ
trên một đối tượng khác nhau. Chỉ có một thread có thể thực hiện bên trong một
instance method. Nếu có nhiều hơn một instance tồn tại, thì một thread ở một thời
điểm có thể được thực thi bên trong synchronized instance method trên mỗi instance.
b) Synchronized static method


public static synchronized void add(int value){
count += value;
}

-

Synchronized static methods thì được đồng bộ trên class object sở hữu các static
method đó. Vì chỉ có một class object tồn tại trong máy ảo Java với mỗi Class, do đó chỉ
có một thread có thể thực hiện bên trong static synchronized method trên một Class.

-

Nếu static synchronized methods được đặt trên các Class khác nhau thì một thread có thể
được thực thi bên trong static synchronized methods của các Class đó.
2.3.2.2 Synchronized blocks
a)

-

Synchronized instance blocks

Chúng ta có thể create một khối synchronize ngay bên trong method. Đôi lúc chúng ta
chỉ muốn xử lý đồng bộ một phần của method.
public void add(int value){
synchronized(this){
this.count += value;
}
}


-

Trong ví dụ này, ta sử dụng Java synchronized block construct để đánh dấu khối xử lý
đồng bộ. Tuy nhiên đoạn mã trên không được thực hiện giống như một synchronized
methods.

-

Chỉ có một thread bên trong Java code block được đồng bộ trên cùng một monitor
object.
10


b)

Synchronized static blocks

public static void add(int value){
synchronized(this){
this.count += value;
}
}

CHƯƠNG 3: CHƯƠNG TRÌNH MINH HỌA VẤN ĐỀ DEADLOCK
TRONG JAVA
3.1Mô tả chương trình:
Xét một hệ thống làm thịt gà gồm 3 thiết bị chính:
-

Thiết bị 1: Nhiệm vụ là cắt cổ gà lấy tiết;


-

Thiết bị 2: Nhiệm vụ là sơ chế gà;

-

Thiết bị 3: Nhiệm vụ là nướng gà và đóng gói.

Nhân viên kỹ thuật được giao nhiệm vụ xây dựng và quản lý hệ thống.
3.2

Môi trường thực hiện:
-

Làm việc trên hệ điều hành Windows 10;

-

Môi trường làm việc: NetBeans IDE version 8.2;

-

Sử dụng JDK: jdk-8u171-nb-8_2-windows-x64.exe.

-

Sử dụng phương thức: Synchronised để minh họa Deadlock

3.3 Triển khai ví dụ:

-

Xét trường hợp, nhân viên kỹ thuật khởi tạo nhầm chương trình vì một số nguyên
nhân hoặc tác động nào đó:
o Thiết bị 1: Sau khi nhận gà và cắt cổ gà thành công. Chuyển sang giai đoạn
tiếp theo là sơ chế gà.
o Thiết bị 2: Sau khi nhận gà và sơ chế gà thành công thì lại chuyển ngược lại
thiết bị 1 => Gây ra deadlock.
11


o Lúc này, thiết bị 3 không thực thi được nhiệm vụ của mình, nguyên nhân là
thiết bị 2 sau khi sơ chế xong thì chuyển ngược lại cắt cổ gà và quá trình cứ
như thế lặp lại.
-

Đoạn code:

-

Kết quả sau khi thực thi chương trình:

-

Giải quyết vấn đề:

12


-


Kết quả sau khi thực thi lại:

13


CHƯƠNG 4: KẾT LUẬN
4.1 Kết luận:
Vấn đề Deadlock trong Java là một chủ đề rất khó. Nó đòi hỏi kinh nghiệm và kỹ năng của
người lập trình viên. Khi viết chương trình hay hệ thống phần mềm cần phải suy nghĩ đến các
trường hợp xảy ra Deadlock để ngăn chặn kịp thời, tránh việc tốn thời gian và chi phí sửa
chữa cũng như không thể giao sản phẩm đúng hạn đến tay khách hàng. Nếu như để xảy ra
Deadlock thì cần phải lựa chọn những phương pháp phù hợp để phục hồi chương trình càng
sớm càng tốt.

4.2 Kết quả thu được:
-

Thông qua việc nghiên cứu “Vấn đề Deadlock trong Java”. Nhóm chúng em đã phần
nào cải thiện được kiến thức về vấn đề deadlock trong hệ điều hành và áp dụng nó để
triển khai trên hệ thống bằng ngôn ngữ Java.

-

Nâng cao khả năng làm việc và giải quyết cũng như ngăn chặn quá trình deadlock xảy
ra trong quá trình lập trình cũng như làm việc với hệ điều hành.

-

Hiểu biết thêm về các phương thức cũng như các thư viện trong Java.


14



×