JavaRush /Blog Java /Random-VI /Bế tắc trong Java là gì?
Alexey Smirnov
Mức độ
Москва

Bế tắc trong Java là gì?

Xuất bản trong nhóm
Mức độ kiến ​​thức cần có để hiểu bài viết: bạn đã hoàn thành nhiệm vụ Cú pháp Java và Java Core và hiện đang trong quá trình học Java Multithreading. Deadlock hay deadlock trong Java hay deadlock là lỗi xảy ra khi các thread có sự phụ thuộc tuần hoàn vào một cặp đối tượng được đồng bộ hóa. Hãy tưởng tượng rằng một luồng đi vào trình giám sát đối tượng xvà luồng kia đi vào trình giám sát đối tượng y. Nếu một luồng trong một đối tượng xcố gắng gọi bất kỳ phương thức được đồng bộ hóa nào trên đối tượng đó yvà đối tượng đó yđồng thời cố gắng gọi bất kỳ phương thức được đồng bộ hóa nào trên đối tượng đó xthì các luồng sẽ bị kẹt khi chờ. Bế tắc là gì?  - 1Dưới đây là một ví dụ từ hướng dẫn tài liệu java về một khái niệm như bế tắc. Việc chặn luồng xảy ra ở đâu ở đây?
public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            @Override
            public void run() {
               // System.out.println("Thread 1");
                alphonse.bow(gaston);
               // System.out.println("Th: gaston bowed to alphonse");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
              //  System.out.println("Thread 2");
                gaston.bow(alphonse);
              //  System.out.println("2.gaston waiting alph bowed");
            }
        }).start();
    }
}
Có hai điều quan trọng cần hiểu ở đây:
  1. Chính xác thì mỗi luồng chạy đồng thời làm gì?
  2. Những loại khóa nào được sử dụng?
Hãy bắt đầu từ cuối. Giả sử bạn đã tạo hai đối tượng của lớp Friend: alphonsegaston. Mỗi người trong số họ có khóa riêng của mình. Vì vậy, có hai ổ khóa như vậy: gigolos và gastons. Khi một phương thức được đồng bộ hóa của một đối tượng được nhập, khóa của nó sẽ bị khóa và khi phương thức đó được thoát, nó sẽ được giải phóng (hoặc mở khóa). Bây giờ về các chủ đề. Hãy gọi chuỗi đầu tiên Alphonse(với chữ in hoa để phân biệt với đối tượng alphonse). Đây là những gì nó làm (hãy gọi nó là A, viết tắt của Alphonse):
A: alphonse.bow(gaston) — получает лок alphonse;
A: gaston.bowBack(alphonse) — получает лок gaston;
A: возвращается из обоих методов, тем самым освобождая лок.
Và đây là những gì thread đang làm vào lúc này Gaston:
G: gaston.bow(alphonse) — получает лок gaston;
G: alphonse.bowBack(gaston) — получает лок alphonse;
G: возвращается из обоих методов, тем самым освобождая лок.
Bây giờ chúng ta hãy tập hợp dữ liệu này lại với nhau và nhận được câu trả lời. Các chủ đề có thể được đan xen (nghĩa là các sự kiện của chúng sẽ xảy ra) theo các thứ tự khác nhau. Ví dụ, bế tắc sẽ xảy ra nếu thứ tự như sau:
A: alphonse.bow(gaston) — получает лок alphonse
G: gaston.bow(alphonse) — получает лок gaston
G: пытается вызвать alphonse.bowBack(gaston), но блокируется, ожидая лока alphonse
A: пытается вызвать gaston.bowBack(alphonse), но блокируется, ожидая лока gaston
Bế tắc là gì?  - 2
Trong trường hợp này, cả hai luồng đều bị chặn và mỗi luồng đang chờ luồng kia nhả khóa. Nhưng không ai trong số họ sẽ làm điều này, bởi vì để làm được điều này, họ cần phải hoàn thành phương thức của mình và nó bị chặn bởi một luồng khác. Vì vậy, họ bị mắc kẹt ở nơi nó xảy ra deadlock. Tuy nhiên, cũng có thể thực hiện một cách dệt khác, trong đó một trong các luồng sẽ có thời gian để hoàn thành trước khi luồng thứ hai bắt đầu:
A: alphonse.bow(gaston) — получает лок alphonse
A: gaston.bowBack(alphonse) — получает лок gaston
A: возвращается из обоих методов, открывая оба лока
G: gaston.bow(alphonse) — получает лок gaston
G: alphonse.bowBack(gaston) — получает лок alphonse
G: возвращается из обоих методов, открывая оба лока
Trong trường hợp này, không có sự chặn lẫn nhau của các luồng. Ví dụ: một số phương thức đã được thêm vào để cho phép một luồng khác có thời gian thực thi. Khi kết quả phụ thuộc vào thứ tự của các sự kiện xảy ra đồng thời (thứ tự dự kiến ​​​​hoặc tốc độ thực hiện), quá trình đó được gọi là điều kiện cuộc đua trong tiếng Nga - “điều kiện cuộc đua”. Không phải tất cả các điều kiện cuộc đua đều có khả năng gây ra bế tắc, tuy nhiên, theo kinh nghiệm của tôi, chỉ có điều kiện cuộc đua mới gây ra bế tắc. Trả lời bởi: Dave Lillehun
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION