Định nghĩa đơn giản về "bất biến": điều kiện luôn đúng trong suốt thời gian tồn tại của đối tượng.
Volatile variables do not share the atomicity features of synchronized
blocks.
Đó là lý do tại sao bạn không thể sử dụng chúng trong lớp có bất biến liên quan đến nhiều biến.
Ví dụ: giả sử bạn có một class
để lập mô hình khoảng thời gian được mô tả bởi hai biến: start
và end
. Một điều kiện bất biến có thể là start
luôn nhỏ hơn hoặc bằng end
. Nếu cả hai biến (như ví dụ) được khai báo là dễ bay hơi thì bạn có thể dựa vào các tính năng hiển thị của volatile
nhưng bạn không thể chắc chắn rằng trong một thay đổi liên quan đến cả hai biến thì bất biến luôn được thỏa mãn. Hãy suy nghĩ:
public void setInterval(Date newStart, Date newEnd)
{
// Check if inputs are correct
// Here the object state is valid
start = newStart;
// If another thread accesses this object now it will
// see an invalid state because start could be greater than end
end = newEnd;
// Here the object state is valid again
}
Trong trường hợp này bạn có thể chắc chắn rằng thay đổi hiển thị cho mọi chuỗi nhưng ở giữa hai hướng, trạng thái đối tượng có thể không hợp lệ. Bởi vì nó có thể được truy cập bởi các chủ đề khác (hãy nhớ đây là một trường hợp đơn giản vì vậy nó có thể nhưng không có khả năng) thì điều kiện bất biến "bắt đầu < kết thúc" có thể bị hỏng.
Đó là lý do tại sao việc sử dụng dễ bay hơi bằng cách nào đó không được khuyến khích bên ngoài một tập hợp các mẫu được xác định rõ. Chỉ nên sử dụng biến dễ bay hơi nếu các điều kiện này được thỏa mãn:
- Biến không liên quan đến bất biến liên quan đến các biến khác (vì lý do được giải thích ở trên).
- Giá trị để viết trên biến không phụ thuộc vào giá trị hiện tại của nó.
Ví dụ biểu thức int a = i++;
không phải là nguyên tử sau đó nó không phải - nói đúng - thread-an toàn vì nó sẽ được viết lại với một cái gì đó như thế này:
int temp = i;
i = i + 1;
int a = temp;
Để làm cho nó nguyên tử từ một quan điểm chủ đề, bạn có thể tưởng tượng một lớp học như thế này:
public class MyAtomicInteger
{
public synchronized increment()
{
x = x + 1;
}
private int x;
}
Tất nhiên nó tồn tại đúng thực tế ntation của AtomicInteger
này và nó là một phần của gói java.util.concurrent.atomic, nó cung cấp một số thói quen cơ bản đơn giản cho lập trình đồng thời không khóa.
Nguồn
2012-03-26 08:40:30
Một số ngữ cảnh khác sẽ hữu ích, nếu không tôi sẽ chỉ đoán ý nghĩa của nó. –
Xin lỗi, tôi đã thêm ngữ cảnh bây giờ –
Trong cuốn sách của tôi là 39 trang – gstackoverflow