2012-10-12 2 views
15

thể trùng lặp:
Java: volatile boolean vs AtomicBooleanSự khác biệt giữa việc sử dụng nguyên thủy dễ bay hơi trên các biến nguyên tử là gì?

Khi nào nó thích hợp để sử dụng một volatile nguyên thủy (ví dụ boolean, integer hoặc long) thay vì AtomicBoolean, AtomicInteger hoặc AtomicLong, và ngược lại?

+0

Vì người ta đã đề cập đến nó (không phải ở đây cũng không trùng lặp): w/Các lớp nguyên tử bạn có một phương thức tiện lợi lazySet. Trên hầu hết các kiến ​​trúc, nó hoạt động tốt hơn viết cơ bản dễ bay hơi (nhưng nó không có cùng ngữ nghĩa). Về cơ bản lazySet không cần phải tuôn ra các bộ đệm ghi CPU mà là khá tốt vì chúng có thể được flushed trong khi CPU bị đình trệ. – bestsss

Trả lời

17

Ngữ nghĩa tầm nhìn giống hệt nhau, tình huống khi sử dụng nguyên thủy nguyên tử hữu ích là khi bạn cần sử dụng các phương pháp nguyên tử của chúng.

Ví dụ:

if (volatileBoolean) { 
    volatileBoolean = !volatileBoolean; 
} 

có thể tạo ra các vấn đề trong một môi trường đa luồng là biến có thể thay đổi giữa hai dòng. Nếu bạn cần sự phân công kiểm tra & được nguyên tử, bạn có thể sử dụng:

atomicBoolean.compareAndSet(true, false); 
+6

'volatileBoolean =! VolatileBoolean;' có thể có một vấn đề luồng chỉ bởi chính nó. –

+0

@PeterLawrey Điểm tốt. – assylias

+1

Bởi vì phủ nhận boolean là một hoạt động hai bước? –

12

Sử dụng một biến động đơn giản là đơn giản và hiệu quả hơn nếu tất cả các bạn muốn làm là thiết lập hoặc lấy giá trị. (Nhưng không nhận được & đặt giá trị)

Nếu bạn muốn nhiều thao tác hơn như getAndIncrement or compareAndSwap bạn cần sử dụng các lớp AtomicXxxx.

+1

Cảm ơn câu trả lời của bạn –

+0

lazySet trên nguyên tử thường thắng trên dễ bay hơi 'viết' (esp trên kiến ​​trúc TSO) nhưng nó có ngữ nghĩa khác nhau. – bestsss

+0

lazySet nhanh hơn vì nó không ngăn cản đường dẫn CPU. –

7

Chúng tôi đã bắt đầu cấm sử dụng volatile trong nguồn của chúng tôi vì rất dễ viết mã không phải lúc nào cũng hoạt động như mong đợi.

Theo kinh nghiệm của tôi, mọi người thêm dễ bay hơi để chia sẻ giá trị giữa các chuỗi. Và sau đó, người khác bắt đầu sửa đổi giá trị. Và hầu hết thời gian, điều này hoạt động. Nhưng trong sản xuất, bạn bắt đầu nhận được các lỗi kỳ lạ mà thực sự khó để theo dõi. Các bộ đếm được tăng lên 100'000 lần (các phép thử chỉ tăng lên 10 lần) nhưng kết thúc ở mức 99'997. Trong Java 1.4, các giá trị dài có thể bị hỏng thực sự, rất hiếm khi.

Các lớp trợ giúp Atomic*, mặt khác, chỉ áp đặt một chi phí nhỏ và chúng luôn hoạt động như được quảng cáo.

Vì vậy, trừ khi bạn có lý do chính đáng (*) để sử dụng volatile, luôn thích các lớp trợ giúp Atomic*.

Nếu bạn không biết chính xác từng ký tự trong lớp trợ giúp Atomic*, thì bạn thực sự nên tránh volatile.

*: Tối ưu hóa sớm không bao giờ là lý do chính đáng.

+0

Cảm ơn câu trả lời của bạn –

+0

* "rất dễ viết mã không phải lúc nào cũng hoạt động như mong đợi." * => Bạn có thể cụ thể hơn không? Bạn có nghĩa là những người giả định dễ bay hơi cho phép đảm bảo nguyên tử chẳng hạn? – assylias

+1

@assylias: Tôi đã thêm một số ví dụ vào câu trả lời của mình. –

7

Lớp Atomic* quấn volatile nguyên thủy cùng loại. Từ nguồn:

public class AtomicLong extends Number implements java.io.Serializable { 
    ... 
    private volatile long value; 
    ... 
    public final long get() { 
     return value; 
    } 
    ... 
    public final void set(long newValue) { 
     value = newValue; 
    } 

So.

Khi nào thích hợp để sử dụng nguyên thủy dễ bay hơi (ví dụ:boolean, integer hoặc dài) thay vì AtomicBoolean, AtomicInteger hoặc AtomicLong

Nếu tất cả các bạn đang làm là nhận và thiết lập một Atomic* sau đó bạn cũng có thể chỉ có một trường volatile để thay thế.

... và ngược lại?

Atomic* lớp cung cấp cho bạn tuy nhiên, phương pháp mà cung cấp chức năng cao cấp hơn như incrementAndGet(), compareAndSet(), và những người khác mà thực hiện nhiều hoạt động (được/increment/bộ, kiểm tra/bộ) mà không khóa. Đó là lý do tại sao các lớp học Atomic* rất mạnh mẽ.

Điều quan trọng cần lưu ý là gói trường volatile của bạn bằng cách sử dụng lớp Atomic* là một cách hay để đóng gói tài nguyên được chia sẻ quan trọng từ quan điểm đối tượng. Điều này có nghĩa là các nhà phát triển không thể đối phó với lĩnh vực giả định rằng nó không được chia sẻ có thể tiêm các vấn đề với một số field++; hoặc mã khác giới thiệu các điều kiện chủng tộc.

+1

Cảm ơn câu trả lời của bạn –