2015-04-04 54 views
0

在并发程序,这是安全的:getter上的volatile和setter上的同步与synchronized上的同步?


private volatile int i; 

public int getI() { 
    return i; 
} 

public synchronized incrementI() { 
    i++; 
} 

根据我所了解的synchronize,只有在获取同一对象上的锁定监视器的线程上,才能保证在i上可用的更改。 所以我认为,上面的代码是不安全的。请确认是否属实,否则请说明。 谢谢。

回答

1

此代码是线程安全的。同步方法内的更改传递到所有线程。 因为你已经使它变得不稳定,所有的线程都不会缓存它,所以会得到最新的拷贝。

而且这个线程将有助于Java volatile modifier and synchronized blocks

+1

不幸的是,这个答案不正确。 “同步方法内部的更改都不会传递到所有线程”,也不会“如果您使其变为易失性,所有线程都不会将其缓存”。这是一个正确的答案:http://stackoverflow.com/a/29446437/2613885 – 2015-04-04 12:32:46

+0

@AlekseyShipilev如果你不使变量易变,那么单独的线程缓存其堆栈中的值。还更新同步块中的变量,并更新其存储它的所有线程中的值。你同意吗?你所说的最终会导致这种情况。那么如何来回答是错误的。 – Lokesh 2015-04-04 13:17:44

+0

看到这篇文章:http://www.javamex.com/tutorials/synchronization_volatile.shtml – Lokesh 2015-04-04 13:18:59

0

由于整数i类的同步实例方法将工作的私有实例变量。您需要确保您添加到修改i的类的所有方法都必须使用同一个对象监视器进行同步。

请注意i ++不是自动表达式,所以只有volatile才会起作用。

您可以像这样使用AtomicInteger作为单个值。

1

几乎精确的例子在“JMM语用学”here中给出。

volatile提供了发生之前的边缘,使得在setter之前发生的所有变化都可见,假设getter实际上观察到了set值。​​另外另外给出互斥,那volatile不保证单独。

+0

你是什么意思*“假设吸气剂实际观察到设定值”*。这是否意味着OP中提供的代码不安全?注:我认为,在并发性方面我是一种新手,在深入挖掘之前需要熟悉一些基本概念。无论如何感谢您的详细信息。我必须研究它。 – artaxerxe 2015-04-07 14:23:48

+0

你是什么意思的“挥发性提供了发生之前的边缘,以便在setter之前进行更改,在getter之后发生的所有事情都可见”?你是否假定执行setter的特定顺序 - > getter? “在setter之前改变”是什么意思? – Chin 2017-05-09 13:37:21

+0

对这两个问题的回答:“假设吸气剂实际观察到设定值”在这里是关键。 * IF * getter观察到由setter设置的值,则setter之前的所有操作都发生在getter之后的任何操作之前。没有什么假定这里的“执行顺序”,JMM只说*如果* volatile读取的是由volatile写入设置的值,则会在before(通过synchronizes-with)出现。 – 2017-05-09 18:47:07