Với mã Java sau:Java wait()/join(): Tại sao điều này không bế tắc?
public class Test {
static private class MyThread extends Thread {
private boolean mustShutdown = false;
@Override
public synchronized void run() {
// loop and do nothing, just wait until we must shut down
while (!mustShutdown) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Exception on wait()");
}
}
}
public synchronized void shutdown() throws InterruptedException {
// set flag for termination, notify the thread and wait for it to die
mustShutdown = true;
notify();
join(); // lock still being held here, due to 'synchronized'
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
Thread.sleep(1000);
mt.shutdown();
} catch (InterruptedException e) {
System.out.println("Exception in main()");
}
}
}
Chạy này sẽ chờ trong một giây và sau đó thoát ra đúng cách. Nhưng điều đó là bất ngờ đối với tôi, tôi mong đợi một khóa chết xảy ra ở đây.
Lý do của tôi như sau: MyThread mới được tạo sẽ thực thi run(), được khai báo là 'đồng bộ', để nó có thể gọi wait() và đọc an toàn 'mustShutdown'; trong suốt cuộc gọi wait() đó, khóa được giải phóng và thu hồi lại khi quay trở lại, như được mô tả trong tài liệu về wait(). Sau một giây, thread chính thực thi shutdown(), một lần nữa được đồng bộ hóa để không truy cập vào mustShutdown cùng lúc khi nó được đọc bởi luồng khác. Sau đó nó đánh thức luồng khác bằng cách thông báo() và chờ hoàn thành thông qua join().
Nhưng theo ý kiến của tôi, không có cách nào mà các chủ đề khác có thể trở về từ wait(), vì nó cần phải lấy lại khóa trên đối tượng thread trước khi trở về. Nó không thể làm như vậy bởi vì shutdown() vẫn giữ khóa trong khi bên trong join(). Tại sao nó vẫn hoạt động và thoát đúng cách?
Đó là vì các tác dụng phụ như thế này kéo dài trực tiếp Chủ đề được cau mày. Bạn nên thực hiện một Runnable mà bạn quấn với một Thread. –