CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.
Bài viết blog CFSDN này Ví dụ khắc phục sự cố bế tắc Java được tác giả sưu tầm và biên soạn. Nếu bạn quan tâm đến bài viết này, hãy nhớ thích nó.
Mục lục
- Ví dụ bế tắc
- Nguyên nhân bế tắc
- Khắc phục sự cố bế tắc
- Tùy chọn 1: jstack
- Tùy chọn 2: jconsole
- Tùy chọn 3: jvisualvm
- Tùy chọn 4: jmc
- Tóm tắt
Bế tắc đề cập đến hai hoặc nhiều đơn vị tính toán (tiến trình, luồng hoặc coroutine), cả hai đơn vị này đều đang chờ đơn vị kia ngừng thực thi để lấy tài nguyên hệ thống, nhưng không có đơn vị nào thoát ra sớm, điều này được gọi là bế tắc.

。
Ví dụ bế tắc
Tiếp theo, trước tiên chúng ta hãy trình diễn deadlock đơn giản nhất trong Java. Chúng ta tạo hai khóa và hai luồng, để luồng 1 sở hữu khóa A trước, sau đó thử lấy khóa B 1 sau đó. Đồng thời, chúng ta bắt đầu luồng 2, hãy để nó trước. giữ khóa B, sau đó cố gắng lấy khóa A 1 giây sau. Lúc này, bên kia sẽ đợi bên kia nhả khóa, gây ra sự cố bế tắc. Mã cụ thể như sau:
public class DeadLockExample { public static void main(String[] args) { Object lockA = new Object(); // Tạo khóa A Object lockB = new Object(); // Tạo khóa B // Tạo thread 1 Thread t1 = new Thread(new Runnable() { @Override public void run() { // Nhận khóa A được đồng bộ hóa đầu tiên (lockA) { System.out.println("Chủ đề 1: Đã lấy được khóa A!"); thử { Thread.sleep(1000); } Catch (InterruptedException e) { e.printStackTrace() } // Thử lấy khóa B System.out .println("Chủ đề 1: Đang chờ lấy khóa B..."); được đồng bộ hóa (lockB) { System.out.println("Chủ đề 1: Đã lấy được khóa B!"); }); t1.start(); // Chạy thread // Tạo thread 2 Thread t2 = new Thread(new Runnable() { @Override public void run() { // Lấy khóa B được đồng bộ hóa lần đầu (lockB) { System. out.println("Chủ đề 2: Đã lấy được khóa B!"); thử { Thread.sleep(1000); } Catch (InterruptedException e) { e.printStackTrace(); } // Cố gắng lấy khóa A System.out.println("Chủ đề 2: Đang chờ lấy khóa A..."); được đồng bộ hóa (lockA) { System.out.println("Chủ đề 2: Đã nhận được khóa A!") ; } } }); t2.start();
Kết quả thực hiện chương trình trên như sau:

Có thể thấy từ kết quả trên cả thread 1 và thread 2 đều đang chờ bên kia nhả khóa, điều này gây ra vấn đề deadlock.
。
Nguyên nhân bế tắc
Qua ví dụ trên, chúng ta có thể kết luận rằng cần phải đáp ứng bốn điều kiện sau để tạo ra bế tắc:
- Điều kiện loại trừ lẫn nhau: có nghĩa là đơn vị tính toán (tiến trình, luồng hoặc coroutine) có quyền truy cập độc quyền vào các tài nguyên được phân bổ, nghĩa là một tài nguyên khóa nhất định chỉ có thể được chiếm bởi một đơn vị tính toán trong một khoảng thời gian.
- Yêu cầu và giữ điều kiện: Có nghĩa là đơn vị tính toán đã duy trì ít nhất một tài nguyên, nhưng đưa ra yêu cầu tài nguyên mới và tài nguyên đó đã bị chiếm giữ bởi đơn vị tính toán khác. Lúc này, đơn vị tính toán yêu cầu bị chặn nhưng vẫn giữ nguyên. các nguồn lực khác mà nó đã có được.
- tình trạng không thể thay đổi: Đề cập đến tài nguyên mà đơn vị tính toán đã thu được và không thể bị tước đoạt trước khi sử dụng hết.
- điều kiện chờ vòng lặp: Đề cập đến khi xảy ra bế tắc, phải có một chuỗi vòng tròn các đơn vị tính toán và tài nguyên, tức là đơn vị tính toán đang chờ tài nguyên bị chiếm bởi đơn vị tính toán khác và đơn vị tính toán kia đang chờ tài nguyên do chính nó chiếm dụng , dẫn đến tình trạng chờ vòng lặp.
Chỉ khi bốn điều kiện trên được đáp ứng cùng lúc thì vấn đề bế tắc mới xảy ra.
。
Khắc phục sự cố bế tắc
Nếu xảy ra sự cố bế tắc trong chương trình, có thể sử dụng một trong 4 giải pháp sau để phân tích và khắc phục sự cố.
。
Tùy chọn 1: jstack
Trước khi sử dụng jstack, trước tiên chúng ta phải lấy ID tiến trình của chương trình đang chạy thông qua jps.

"jps -l" có thể truy vấn tất cả các chương trình Java trên máy này. jps (Công cụ trạng thái quy trình máy ảo Java) là một lệnh do Java cung cấp để hiển thị pid của tất cả các quy trình Java hiện tại. Nó phù hợp để chỉ xem các chương trình Java hiện tại trên. nền tảng linux/unix/windows. Đối với một số trường hợp đơn giản của quy trình, "-l" được sử dụng để xuất pid quy trình và tên đường dẫn đầy đủ của chương trình đang chạy (tên gói và tên lớp).
Với ID tiến trình (PID), chúng ta có thể sử dụng "jstack -l PID" để tìm ra vấn đề bế tắc, như trong hình sau:

jstack được sử dụng để tạo ảnh chụp nhanh luồng của máy ảo Java tại thời điểm hiện tại. "-l" biểu thị một danh sách dài (dài) và in thông tin bổ sung về khóa.
PS: Bạn có thể sử dụng jstack -help để xem thêm hướng dẫn lệnh.
。
Tùy chọn 2: jconsole
Để sử dụng jconsole, bạn cần mở thư mục bin của JDK, tìm jconsole và nhấp đúp để mở nó, như thể hiện trong hình sau:

Sau đó chọn chương trình bạn muốn gỡ lỗi, như thể hiện trong hình bên dưới:

Sau đó click vào kết nối để vào, chọn “Insecure Connection” để vào trang chủ giám sát, như hình bên dưới:


Sau đó chuyển sang mô-đun "Thread" và nhấp vào nút "Phát hiện bế tắc", như trong hình bên dưới:

Sau một thời gian, các thông tin liên quan đến deadlock sẽ được phát hiện, như thể hiện trong hình bên dưới:

。
Tùy chọn 3: jvisualvm
jvisualvm cũng nằm trong thư mục bin của JDK. Nó cũng có thể được mở bằng cách nhấp đúp:

Sau vài giây, tất cả các chương trình Java cục bộ sẽ xuất hiện trong jvisualvm, như trong hình bên dưới:

Bấm đúp để chọn chương trình cần gỡ lỗi:

Sử dụng chuột máy đơn để vào mô-đun "Thread", như trong hình bên dưới:

Như có thể thấy từ hình trên, khi chúng ta chuyển sang cột luồng, thông tin bế tắc sẽ được hiển thị trực tiếp, sau đó nhấp vào "Kết xuất luồng" để tạo thông tin chi tiết về bế tắc, như trong hình bên dưới:

。
Tùy chọn 4: jmc
jmc là tên viết tắt của Oracle Java Mission Control, là bộ công cụ để quản lý, giám sát, lập hồ sơ và khắc phục sự cố các chương trình Java. Nó cũng nằm trong thư mục bin của JDK và có thể được khởi động bằng cách nhấp đúp vào nó, như trong hình bên dưới:

Thông tin trang chủ jmc như sau:

Sau đó chọn chương trình cần kiểm tra, nhấp chuột phải vào "Khởi động Bảng điều khiển JMX" để xem chi tiết về chương trình này, như trong hình sau:


Sau đó nhấp vào "Chủ đề" và kiểm tra "Phát hiện bế tắc" để tìm các bế tắc và chi tiết bế tắc, như trong hình bên dưới:

。
Tóm tắt
Bế tắc xảy ra do hai hoặc nhiều đơn vị tính toán đang đợi nhau ngừng thực thi để lấy tài nguyên hệ thống nhưng không có ai thoát ra sớm nên xảy ra bế tắc. Có tổng cộng 4 công cụ khắc phục sự cố bế tắc:
- jstack
- jconsole
- vietanh
- jmc
Từ góc độ dễ sử dụng và hiệu suất, nên sử dụng jconsole hoặc jvisualvm để khắc phục sự cố bế tắc.
Tài liệu tham khảo & Lời cảm ơn.
blog.csdn.net/u010648555/article/details/80721815 。
cnblogs.com/cxuanBlog/p/13202898.html 。
zh.wikipedia.org/zh-hans/Deadlock.
Trên đây là chi tiết về các ví dụ khắc phục sự cố deadlock Java. Để biết thêm thông tin về cách khắc phục sự cố deadlock Java, vui lòng theo dõi các bài viết liên quan khác của tôi! .
Liên kết gốc: https://www.cnblogs.com/vipstone/p/15178628.html.
Cuối cùng, bài viết về các ví dụ khắc phục sự cố bế tắc Java này kết thúc tại đây. Nếu bạn muốn biết thêm về các ví dụ khắc phục sự cố bế tắc Java, vui lòng tìm kiếm các bài viết về CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!