1

请举这个非常简单的例子:

volatile int globalVar = 1;

我的线程:

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

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

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

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

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

我对吗?

4

4 回答 4

2

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

于 2013-07-08T16:50:23.313 回答
1

不,它不是线程安全的。Volatile 不保证原子性。像 i-- 这样的操作不是原子的,所以将 i 声明为 volatile 没有帮助。

int globalVar = 1;

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

}finally {
   lock.unlock();
}

上面的代码可以工作,你不需要在这里将 gobalVar 声明为 volatile,因为
Volatile 提供了两个保证:1. 可见性 2. 重新排序

然而

同步/锁定/解锁三保证 1.原子性 2.可见性 3.重排序

还要记住,只要在多个线程之间共享一个对象,总是在任何同步操作同步/易失性读/写下访问该对象。

在这里阅读 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

于 2013-07-08T17:23:39.890 回答
0

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

synchronized(this)
{
 if (globalVar > 0) {
   globalVar--;
 }
}
于 2013-07-18T08:26:27.350 回答
0

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

可以做的一个例子:

volatile Integer globalVar = 1;

然后在完成工作的方法中,您可以:

synchronized public void decrement(){
    if(globalVar > 0)
          globalVar--;
    }
}
于 2013-07-08T17:03:16.607 回答