2010-02-27 45 views
7

Tôi đã đọc về cuốn sách 'Lập trình đồng thời trong Java' của Doug Lea. Như bạn đã biết, Doug ban đầu đã viết API đồng thời Java. Tuy nhiên, một cái gì đó đã gây ra cho tôi một số nhầm lẫn và tôi đã hy vọng đạt được một vài ý kiến ​​của tôi về câu hỏi hóc búa này!Đồng bộ hóa một Hàng đợi

Đi đoạn mã sau từ ví dụ xếp hàng Doug Lea của ...

class LinkedQueue { 
    protected Node head = new Node(null); 
    protected Node last = head; 

    protected final Object pollLock = new Object(); 
    protected final Object putLock = new Object(); 

    public void put(Object x) { 
    Node node = new Node(x); 
    synchronized (putLock) {  // insert at end of list 
     synchronized (last) { 
     last.next = node;  // extend list 
     last = node; 
     } 
    } 
    } 

    public Object poll() {   // returns null if empty 
    synchronized (pollLock) { 
     synchronized (head) { 
     Object x = null; 
     Node first = head.next; // get to first real node 
     if (first != null) { 
      x = first.object; 
      first.object = null; // forget old object 
      head = first;   // first becomes new head 
     } 
     return x; 
     } 
    } 
    } 

    static class Node {   // local node class for queue 
    Object object; 
    Node next = null; 

    Node(Object x) { object = x; } 
    } 
} 

này một khá Queue tốt đẹp. Nó sử dụng hai màn hình để một nhà sản xuất và một người tiêu dùng có thể truy cập vào hàng đợi cùng một lúc. Tốt đẹp! Tuy nhiên, đồng bộ hóa trên 'cuối cùng' và 'đầu' là khó hiểu tôi ở đây. Cuốn sách nói rằng điều này là cần thiết cho tình huống trong đó Hàng đợi hiện tại hoặc sắp có 0 mục nhập. Ok, đủ công bằng và loại ý nghĩa này.

Tuy nhiên, sau đó tôi đã xem Java Concurrency LinkedBlockingQueue. Phiên bản original của Hàng đợi không đồng bộ hóa trên đầu hoặc đuôi (Tôi cũng muốn đăng liên kết khác lên phiên bản hiện đại cũng gặp vấn đề tương tự nhưng tôi không thể làm như vậy vì tôi là người mới). Tôi tự hỏi tại sao không? Am i thiếu cái gì ở đây? Có một phần nào đó của bản chất riêng của Mô hình bộ nhớ Java mà tôi đang thiếu không? Tôi đã có thể nghĩ cho mục đích hiển thị rằng đồng bộ hóa này là cần thiết? Tôi đánh giá cao một số ý kiến ​​chuyên gia!

+0

Xin lưu ý, lý thuyết hiện tại của tôi nằm về phương thức 'signalNotEmpty' nhập khối được đồng bộ hóa cho 'takeLock'. Điều này có lẽ sẽ buộc 'đầu' được nhìn thấy. –

Trả lời

2

Trong phiên bản bạn đặt liên kết cũng như phiên bản trong JRE mới nhất, mục bên trong lớp Node dễ bay hơi thực thi đọc và ghi để hiển thị cho tất cả các chủ đề khác, dưới đây là giải thích chi tiết hơn http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

+0

Cảm ơn, vâng tôi thấy bây giờ. Việc ghi vào một biến dễ bay hơi sẽ có tác dụng tương tự như việc phát hành một màn hình đồng bộ hóa và do đó vấn đề hiển thị được giải quyết. –

2

Sự tinh tế ở đây là đồng bộ (null) sẽ ném NullPointerException, vì vậy cả đầu và cuối đều không được phép trở thành rỗng. Cả hai đều được khởi tạo thành giá trị của cùng một nút giả mà không bao giờ được trả lại hoặc bị xóa khỏi danh sách.

put() và poll() được đồng bộ hóa trên hai khóa khác nhau. Các phương thức sẽ cần phải đồng bộ hóa trên cùng một khóa để được an toàn thread đối với nhau nếu chúng có thể sửa đổi cùng một giá trị từ các luồng khác nhau. Tình huống duy nhất trong đó vấn đề này là khi đầu == cuối cùng (tức là chúng là cùng một đối tượng, được tham chiếu qua các biến thành viên khác nhau). Đây là lý do tại sao mã đồng bộ hóa trên đầu và cuối - hầu hết thời gian sẽ nhanh chóng, không có khóa, nhưng đôi khi đầu và cuối cùng sẽ là cùng một thể hiện và một trong các chủ đề sẽ phải chặn khác.

Thời gian duy nhất khả năng hiển thị là vấn đề khi hàng đợi gần hết, phần còn lại của thời gian put() và poll() hoạt động trên các đầu khác nhau của hàng đợi và không can thiệp lẫn nhau.

+0

Cảm ơn câu trả lời. Thật thú vị mặc dù vấn đề chính ở đây xung quanh việc đồng bộ hóa đầu và cuối cùng thực sự là khả năng hiển thị. Thật thú vị khi thấy mức độ hiển thị đạt được trong LinkedBlockingQueue của gói tương tranh bằng một phương tiện thay thế. Đây là những gì thực sự hấp dẫn tôi. –

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