Sau khi thực hiện wait (), một luồng sẽ đợi bao lâu nếu nó không nhận được thông báo từ các luồng khác?

Aug 16 2020

Trong ví dụ dưới đây, vì luồng chính không nhận được thông báo từ luồng con, nên nó sẽ đợi mãi mãi. Nhưng luồng chính đang được thực thi và kết quả của ví dụ dưới đây là:

c
l
total: 19900

Tại sao luồng chính được thực thi?

public class ThreadX extends Thread {
    static int total = 0;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 200; i++) {
                total = total + i;
            }
            System.out.println("c");

        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadX t = new ThreadX();

        t.start();
        synchronized (t) {
            t.wait();
            System.out.println("l");
        }

        System.out.println("total: " + total);

    }
}

Trả lời

10 akuzminykh Aug 16 2020 at 09:58

Câu trả lời cho phần câu hỏi

Kiểm tra Thread#join(long):

[...] Khi một luồng kết thúc this.notifyAllphương thức được gọi. [...]

Lưu ý rằng Thread#join()gọi hàm đó với 0, có nghĩa là mãi mãi.

[...] Thời gian chờ bằng 0 có nghĩa là chờ đợi mãi mãi.

Vì vậy, trong trường hợp của bạn ở đây tchỉ gọi notifyAllkhi nó kết thúc, điều này sẽ thông báo cho luồng chính đang chờ t.


Hành vi không trực quan này là lý do tại sao họ viết như sau trong tài liệu:

Đó là khuyến cáo rằng các ứng dụng không sử dụng wait, notifyhoặc notifyAllvào Threadtrường.

Câu trả lời cho câu hỏi-tiêu đề

Kiểm tra Object#wait(hoặc JLS (17.2.1. Chờ) ):

Một chuỗi có thể đánh thức mà không bị thông báo, bị gián đoạn hoặc hết thời gian, được gọi là đánh thức giả. Trong khi điều này hiếm khi xảy ra trong thực tế, các ứng dụng phải đề phòng nó bằng cách kiểm tra điều kiện mà lẽ ra phải đánh thức luồng và tiếp tục chờ nếu điều kiện không được thỏa mãn.

Vì vậy, các luồng trong Java có thể đánh thức bất cứ lúc nào. Việc đánh thức giả không có khả năng xảy ra nhưng nó có thể xảy ra.