2011-01-26 30 views
5

Brian Goetz đã viết một bài viết hay về ngã ba tại số http://www.ibm.com/developerworks/java/library/j-jtp03048.html. Trong đó, anh ta liệt kê một thuật toán sắp xếp hợp nhất bằng cách sử dụng cơ chế fork-join, trong đó anh ta thực hiện sắp xếp trên hai mặt của một mảng song song, sau đó kết hợp kết quả.Khả năng hiển thị bộ nhớ trong Fork-join

Thuật toán sắp xếp trên hai phần khác nhau của cùng một mảng cùng một lúc. Tại sao không phải là AtomicIntegerArray hoặc một số cơ chế khác cần thiết để duy trì khả năng hiển thị? Những gì đảm bảo là có một sợi sẽ thấy các ghi được thực hiện bởi người khác, hoặc là một lỗi tinh tế? Theo dõi, ForkJoinScheduler của Scala cũng đảm bảo điều này?

Cảm ơn!

+0

Chúng hoạt động trên các phần khác nhau của mảng. Không có tranh chấp cho đến khi sáp nhập. –

+3

Tôi đồng ý rằng họ đang hoạt động trên các phần khác nhau. Nhưng ngữ nghĩa của mô hình bộ nhớ của Java nhiều hay ít nói rằng không phải tất cả các luồng đều được đảm bảo để xem tất cả các ghi (trừ khi biến là biến động). Theo blog này: http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html thậm chí sử dụng một int dễ bay hơi [] là không đủ để đảm bảo rằng các chủ đề khác nhìn thấy ghi của bạn vào mảng –

Trả lời

5

Bản thân tham gia (của ForkJoin) yêu cầu điểm đồng bộ hóa, đó là phần thông tin quan trọng nhất. Một điểm đồng bộ sẽ đảm bảo rằng tất cả các ghi xảy ra đều có thể nhìn thấy sau điểm được nói.

Nếu bạn xem mã, bạn có thể thấy nơi xảy ra điểm đồng bộ hóa. Đây chỉ là một cuộc gọi phương thức invokeAll

public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) { 
    t2.fork(); 
    t1.invoke(); 
    t2.join(); 
} 

Tại đây t2 tiến hành một quá trình khác, t1 thực hiện nhiệm vụ của nó và chuỗi đang chờ sẽ chờ t2.join(). Khi vượt qua t2. Tất cả ghi vào t1 và t2 sau đó sẽ được hiển thị.

Chỉnh sửa: Chỉnh sửa này chỉ nhằm cung cấp thêm một chút giải thích về ý nghĩa của tôi bằng điểm đồng bộ hóa.

Cho phép nói rằng bạn có hai biến

int x; 
volatile int y; 

Bất cứ lúc nào bạn viết thư cho y tất cả viết đã xảy ra trước khi bạn đọc y sẽ có sẵn. Ví dụ

public void doWork(){ 
    x = 10; 
    y = 5; 
} 

Nếu thread khác đọc y = 5 mà chủ đề là đảm bảo để đọc x = 10. Điều này là do ghi vào y tạo ra một điểm đồng bộ hóa trong đó tất cả viết trước khi nói điểm sẽ có thể nhìn thấy sau khi viết.

Với nhóm Tham gia ngã ba, sự tham gia của ForkJoinTask sẽ tạo một điểm đồng bộ hóa. Bây giờ, nếu t2.fork() và t1.invoke(), việc nối của t2 sẽ đảm bảo rằng tất cả các bài viết mà trước đây đã xảy ra sẽ được nhìn thấy. Vì tất cả các bài viết trước đều nằm trong cùng một cấu trúc, nó sẽ an toàn cho khả năng hiển thị.

Tôi rất sẵn lòng giải thích thêm nếu điều đó không rõ ràng.

+0

Có phải 'invokeAll' được gọi bởi' coInvoke'? –

+0

Và, chỉ để bổ sung cho câu trả lời, xem thêm http://java.sun.com/docs/books/jls/third_edition/html/memory.html#64058. –

+0

@Danciel C. Sobral thú vị bạn hỏi, khi tôi đã viết ví dụ này tôi đã thực sự tìm kiếm phương pháp coInvoke. Có vẻ như chính phương thức coInvoke đã bị xóa khỏi mã nguồn. Đó là ít nhất tôi không thể tìm thấy nó nữa. –

1

Chỉ cần đoán: hợp nhất bao gồm việc tham gia vào một Chủ đề và tham gia đảm bảo khả năng hiển thị.

Phần thứ hai chắc chắn; Tôi không biết cách hợp nhất được triển khai.

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