繁体   English   中英

volatile如何使我的课程成为线程安全的?

[英]How does volatile make my class thread-safe?

我有一堂课

public class X {
    private volatile int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

它是线程安全的吗? 我认为即使添加volatile关键字也不是线程安全的。

线程安全性可以表示为“如果类的对象在多线程环境中的行为与在单线程环境中的行为完全相同,则它是线程安全的”,或者相反,我们可以说“行为完全相同” “行为正确”。

就您而言,正确的行为意味着在调用setValue(N) ,以下getValue()返回N 如果您不使用volatile修饰符,则仅在单线程环境中才是正确的:如果您在Thread1上调用setValue(N) ,那么在Thread2上调用getValue()之后,它不一定会返回N 问题在于Thread1和Thread2可能在单独的CPU内核上执行,并且CPU内核通常不直接读写共享内存:两个处理器可以具有单独的CPU缓存,而setValue(N)调用只能修改CPU缓存的value成员的副本,因此该更改对于RAM不会立即可见。 此外,即使N在共享内存中已经可用, getValue()可以从第二个处理器缓存中读取一个已缓存但过时的值。 因此,您在Thread1上执行的值更改可能不会立即在Thread2上可见,因此getValue()可能会返回不建议使用的值。

volatile修饰符通过以下两个属性对其进行求解:

  • 写入易失性值后,它不仅会存储在CPU缓存中,还会立即刷新到共享RAM中
  • 读取易失性值将始终从内存中读取它,而不是从CPU缓存中读取它。

简单地回答您的问题:当变量将被多个线程访问并且您不想/不需要锁定它时,应该使用volatile。 从您提供的示例中, get可能会出现“线程安全”问题(请参见erosb的答案)

另外:volatile的使用受到限制,因此我强烈建议您使用AtomicInteger ,它同时提供原子性和易变性(AtomicInteger类将其value字段存储在volatile变量中)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM