Java中的波动性和线程安全性

时间:2013-07-08 16:47:16

标签: java multithreading thread-safety race-condition volatile

请采用这个非常简单的例子:

volatile int globalVar = 1;

我的主题:

if (globalVar > 0) {
    globalVar--;
}

现在,我必须决定使变量volatile变得足以防止竞争条件并使这个线程安全。

我知道递增和递减不是,但由于前面的条件,我不确定它是否不同。

我认为它仍然不安全,因为它可以按此顺序执行:

线程A检查条件。线程B检查条件。 线程A递增。线程B递增。

我是对的吗?

4 个答案:

答案 0 :(得分:2)

你是对的。由于您声明的原因,它不是线程安全的。 volatile确保两个线程都能看到变量的更新值,但不能保护多行代码。

答案 1 :(得分:1)

不,它不是线程安全的。 挥发性不保证原子性。操作如 我 - 不是原子的,所以宣称我不稳定并没有帮助。

int globalVar = 1;

lock.lock()
try{
  if(globalVar > 0)
          globalVar--;

}finally {
   lock.unlock();
}

上面的代码可以使用,你不需要在这里声明golbalVar为volatile 因为
挥发性有两个保证: 1.可见性 2.重新排序

同步/锁定/解锁给予三个保证 1.Atomicity 2.可见性 3.Reordering

另外请记住,无论何时在多个线程之间共享Object,始终都可以访问它 任何同步动作同步/易失性读/写下的对象。

阅读JLS作者第17章的优秀文章。这是必读的 http://jeremymanson.blogspot.in/2008/11/what-volatile-means-in-java.html http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html

答案 2 :(得分:0)

要使代码线程安全,您需要在检查和修改周围添加synchronized块。

可以做的事情的一个例子:

volatile Integer globalVar = 1;

然后在完成工作的方法中:

synchronized public void decrement(){
    if(globalVar > 0)
          globalVar--;
    }
}

答案 3 :(得分:0)

volatile不保证原子性。你可以简单地添加一个同步块。

synchronized(this)
{
 if (globalVar > 0) {
   globalVar--;
 }
}