2010-05-07 35 views
64

Trong ArrayBlockingQueue, tất cả các phương pháp yêu cầu khóa bản sao nó vào một biến địa phương final trước khi gọi lock().Trong ArrayBlockingQueue, tại sao sao chép trường thành viên cuối cùng vào biến cuối cùng cục bộ?

public boolean offer(E e) { 
    if (e == null) throw new NullPointerException(); 
    final ReentrantLock lock = this.lock; 
    lock.lock(); 
    try { 
     if (count == items.length) 
      return false; 
     else { 
      insert(e); 
      return true; 
     } 
    } finally { 
     lock.unlock(); 
    } 
} 

Có lý do nào để sao chép this.lock cho một biến địa phương lock khi lĩnh vực this.lockfinal?

Ngoài ra, nó còn sử dụng một bản sao cục bộ của E[] trước khi hành động trên nó:

private E extract() { 
    final E[] items = this.items; 
    E x = items[takeIndex]; 
    items[takeIndex] = null; 
    takeIndex = inc(takeIndex); 
    --count; 
    notFull.signal(); 
    return x; 
} 

Có bất kỳ lý do để sao chép một lĩnh vực thức cho một biến thức địa phương?

Trả lời

52

Đó là một tối ưu hóa cực kỳ Doug Lea, tác giả của lớp, thích sử dụng. Đây là một bài đăng trên a recent thread trên danh sách gửi thư lõi-libs-dev về chủ đề chính xác này, câu trả lời cho câu hỏi của bạn khá tốt.

từ đăng bài:

... sao chép để người dân địa phương tạo ra bytecode nhỏ nhất, và cho mã ở mức độ thấp nó rất hay để viết mã đó là một chút gần gũi hơn với các máy

+11

mạnh nhấn mạnh về "cực đoan"! Đây không phải là một thực hành lập trình tốt mục đích chung mà tất cả mọi người nên được thi đua. –

+12

Ngẫu nhiên FYI: trong một số trường hợp khác khi bạn thấy điều này được thực hiện, đó là vì trường được đề cập là dễ bay hơi và phương pháp cần đảm bảo rằng nó có giá trị nhất quán duy nhất hoặc tham chiếu cho nó trong suốt. –

+2

Tôi sẽ thực hiện tối ưu hóa "cực đoan" này trong một lớp lõi như thế này. –

9

This thread cung cấp một số câu trả lời. Trong chất:

  • trình biên dịch không thể dễ dàng chứng minh rằng một lĩnh vực thức không thay đổi trong vòng một phương pháp (do phản xạ/serialization vv) trình biên dịch
  • mới nhất thực sự không cố gắng và do đó sẽ có để tải lại mọi lĩnh vực thức nó được sử dụng mà có thể dẫn đến một cache hoặc một lỗi trang
  • lưu trữ nó trong một biến địa phương buộc JVM để thực hiện chỉ có một tải
+1

Tôi không nghĩ rằng biến 'final' phải được tải lại bởi JVM. Nếu bạn sửa đổi biến 'final' thông qua sự phản chiếu, bạn sẽ mất bảo đảm cho chương trình của mình hoạt động chính xác (nghĩa là giá trị mới có thể không được tính đến trong mọi trường hợp). – icza

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