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!
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. –