2015-02-16 14 views
5

Mã này là từ hiệu quả Java (khoản 66): (không đồng bộ hoặc không ổn định này không bao giờ kết thúc)Tại sao luồng hoạt động khác với thân phương pháp chạy khác nhau?

public class ThreadPractice { 
static boolean canrunstatic; 

public static void main(String[] args) throws InterruptedException { 

    Thread backgroundThread = new Thread(new Runnable() { 
     public void run() { 
      int i = 0; 
      while (!canrunstatic){i++;} 
      System.out.println("finished"); 
     } 
    }); 
    backgroundThread.start(); 
    TimeUnit.SECONDS.sleep(1); 
    canrunstatic = true; 
} 

Như Bloch đề cập trong chương rằng nó sẽ không bao giờ viết "xong" ra cửa sổ Console. Tôi đã chơi xung quanh với lớp này và thêm dòng đó vào phương thức chạy runnable:

System.out.println("im still running"); 

Với vòng lặp while này không chỉ tăng i mà in ra chuỗi này trong mỗi vòng lặp. Nhưng điều khiến tôi phát điên, theo cách này, sợi chỉ dừng lại sau 1 giây, khi sợi chính quay trở lại từ giấc ngủ.

chỉnh sửa: (dừng mà không dễ bay hơi/sync)

public class ThreadPractice { 
static boolean canrunstatic; 


public static void main(String[] args) throws InterruptedException { 

    Thread backgroundThread = new Thread(new Runnable() { 
     public void run() { 
      int i = 0; 
      while (!canrunstatic){i++;System.out.println("im still running");} 
      System.out.println("finished"); 
     } 
    }); 
    backgroundThread.start(); 
    TimeUnit.SECONDS.sleep(1); 
    canrunstatic = true; 


} 

Vì vậy, logic đằng sau này là gì?

Trả lời

4

Chính xác, nó chỉ là không được bảo đảm rằng các chủ đề bao giờ sẽ dừng lại, nhưng nó là không cấm nó dừng lại. Logic đằng sau điều này được cung cấp bởi Java Memory Model, đây là một chủ đề khá phức tạp, nhưng cần thiết để hiểu được Đa luồng trong Java.

Khái niệm là ghi vào trường không bay hơi của một sợi chỉ yêu cầu được xem bởi một chuỗi khác nếu hai hành động này đồng bộ hóa với nhau. Trình biên dịch cho phép sắp xếp lại một số hành động nếu hành vi được hiển thị bởi luồng mà nó được thực hiện trong không thay đổi. Nhưng một chủ đề khác có thể thấy điều này. Vì vậy, bạn cần đồng bộ hóa thích hợp để cho trình biên dịch biết sắp xếp lại không được phép trong một số phần.

Đọc bài báo đầy đủ về điều này tại đây: JSR-133

2

Ghi dữ liệu vào bảng điều khiển thường được thực hiện một thao tác an toàn chỉ.

Trong trường hợp đó, hành vi ghi dữ liệu của bạn vào bảng điều khiển cũng có thể kích hoạt cập nhật biến số canrunstatic như được xem bởi backgroundThread của bạn.

Lưu ý rằng điều này là không được hứa hẹn bởi Memory Model Java, cũng không phải bởi việc thực hiện các java System.out

+2

Điều đó không được chỉ định ở bất kỳ đâu trong mô hình bộ nhớ. Việc ghi vào bàn điều khiển là một hoạt động bên ngoài trong JMM, nhưng điều này không đảm bảo việc đồng bộ hóa và các khoản phí không tạo ra một cạnh đồng bộ hóa. Vì vậy, đây không phải là một lời giải thích cho logic đằng sau này. – MinecraftShamrock

+0

Điểm tốt, đây là nguyên nhân, nhưng không bắt buộc phải xảy ra. Tôi đã cập nhật câu trả lời để phản ánh điều này. – Thirler

Các vấn đề liên quan