Tôi có một đoạn mã mà trông như thế này:Biến Java biến động có áp đặt mối quan hệ xảy ra trước khi nó được đọc không?
Snippet A:
class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() {
return numCreated;
}
}
Từ hiểu biết của tôi, kể từ khi đọc numCreated
không đồng bộ, nếu Chủ đề-A tạo ra một Creature
tại 13:00 và Thread-B đọc numCreated()
lúc 2 giờ chiều, numCreated()
cũng có thể trả về 0 hoặc 1 (ngay cả khi Thread-A đã hoàn tất khởi tạo đối tượng lúc 1.05pm).
Vì vậy, tôi đã thêm synchronized
để numCreated()
:
Snippet B:
class Creature {
private static long numCreated;
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static synchronized long numCreated() { // add "synchronized"
return numCreated;
}
}
và tất cả là tốt, ngoại trừ việc tôi đã suy nghĩ, nếu tôi sửa đổi nó để Snippet C, là biến numCreated
vẫn được đồng bộ hóa đúng cách?
Snippet C:
class Creature {
private static volatile long numCreated; // add "volatile"
public Creature() {
synchronized (Creature.class) {
numCreated++;
}
}
public static long numCreated() { // remove "synchronized"
return numCreated;
}
}
Với Snippet C, là nó đảm bảo rằng càng sớm càng Chủ đề-A hoàn thành đối tượng sáng tạo lúc 1:05 giờ chiều, cuộc gọi Thread-B để numCreated()
chắc chắn sẽ trở lại 1
?
PS: Tôi hiểu rằng trong một tình huống thực sự tôi có lẽ sẽ sử dụng một AtomicLong
nhưng điều này là dành cho mục đích học tập
lượt đọc dễ bay hơi rẻ, đây là những gì bạn cần biết. Tuy nhiên, viết không phải là giá rẻ, mặc dù. Đồng bộ hóa đòi hỏi cả một viết dễ bay hơi và CAS (so sánh và thiết lập), cộng với màn hình contended bảo lãnh cho hệ điều hành đó là động lực để khóa-miễn phí impl. – bestsss
đưa ra nhận xét trước, không cố gắng chơi * thông minh hơn * bằng cách loại bỏ dễ bay hơi. – bestsss
@bestsss Tôi không hiểu nhận xét cuối cùng của bạn, ý của bạn là gì khi không loại bỏ dễ bay hơi? (trong Snippet C tôi đã thêm dễ bay hơi và loại bỏ đồng bộ) – Pacerier