Volatile Vs Atomic
我在下面的某个地方看书。
Java volatile keyword doesn't means atomic, its common misconception
that after declaring volatile,++ operation will be atomic, to make
the operation atomic you still need to ensure exclusive access using
synchronized method or block in Java.
那么,如果两个线程同时攻击一个
这是否意味着任何人锁定它,将首先设置它的值。如果同时,当第一个线程改变它的值时,另一个线程出现并读取旧值,那么新线程不会读取它的旧值吗?
原子关键字和易失性关键字有什么区别?
然而,值得注意的是,一个需要多个读/写的操作(如
挥发性和原子性是两个不同的概念。volatile确保特定的预期(内存)状态在不同的线程之间是真的,而atomics确保对变量的操作是原子执行的。
以Java中的两个线程为例:
线程A:
1 2 | value = 1; done = true; |
线程B:
1 2 |
从
作为volatile的副作用,这样一个变量的值被原子地设置为线程范围(执行速度的代价非常小)。然而,这只在32位系统上很重要,即使用长(64位)变量(或类似变量),在大多数其他情况下,设置/读取变量无论如何都是原子的。但是原子访问和原子操作之间有一个重要的区别。volatile只确保访问是原子性的,而atomics确保操作是原子性的。
举个例子:
1 | i = i + 1; |
无论如何定义i,在执行上述行时读取值的不同线程可能会得到i或i+1,因为该操作不是原子性的。如果另一个线程将i设置为不同的值,在最坏的情况下,线程a可以将我设置回以前的值,因为它只是在根据旧值计算i+1的中间,然后再次将i设置为旧值+1。说明:
1 2 3 4 |
像atomicinteger这样的原子确保这样的操作是原子性的。所以上面的问题不会发生,一旦两个线程都完成了,我将是1000或1001。
在多线程环境中有两个重要的概念。
因此,即使您向
但是,
正如所指出的,
在并发环境中考虑此代码段:
1 2 3 4 5 6 7 | boolean isStopped = false; : : while (!isStopped) { // do some kind of work } |
这里的想法是,一些线程可以将EDOCX1的值(28)从false更改为true,以便向后续循环指示是时候停止循环了。
直观地说,没有问题。逻辑上,如果另一个线程使
这样做的原因并不直观,但要考虑到现代处理器有多个内核,并且每个内核都有多个寄存器和多个缓存级别,其他处理器无法访问这些寄存器和缓存级别。换句话说,缓存在一个处理器本地内存中的值对在不同处理器上执行的线程不可见。这就是并发性的核心问题之一:可见性。
Java内存模型不能保证对线程中变量的更改可能对其他线程可见。为了确保更新一经创建就可以访问,必须进行同步。
使用
- 使非原子64位操作具有原子性:
long 和double 。(所有其他的原始访问都保证是原子的!) - 为了确保变量更新被其他线程看到+可见性效果:在写入可变变量之后,在写入该变量之前可见的所有变量在读取相同可变变量之后(在排序之前发生)对其他线程可见。
根据Java文档,EDCOX1的3个类是:
A small toolkit of classes that support lock-free thread-safe
programming on single variables. In essence, the classes in this
package extend the notion of volatile values, fields, and array
elements to those that also provide an atomic conditional update
operation of the form:
boolean compareAndSet(expectedValue, updateValue);
原子类是围绕原子
来自Java文档:
When a thread sees an update to an atomic variable caused by a
weakCompareAndSet, it does not necessarily see updates to any other
variables that occurred before the weakCompareAndSet.
关于你的问题:
Does this mean that whosoever takes lock on it, that will be setting
its value first. And in if meantime, some other thread comes up and
read old value while first thread was changing its value, then doesn't
new thread will read its old value?
您不锁定任何东西,您描述的是一个典型的竞争条件,如果线程在没有适当同步的情况下访问共享数据,最终会发生这种情况。如前所述,在这种情况下声明变量
What is the difference between
AtomicInteger andvolatile int ?
So what will happen if two threads attack a volatile primitive variable at same time?
通常每个都可以增加值。但是,有时两个线程都会同时更新值,而不是增加2个总数,而是同时增加1个线程和1个线程。
Does this mean that whosoever takes lock on it, that will be setting its value first.
没有锁。这就是
And in if meantime, some other thread comes up and read old value while first thread was changing its value, then doesn't new thread will read its old value?
对,
What is the difference between Atomic and volatile keyword?
atomicXXXX包装了一个volatile,所以它们基本相同,区别在于它提供了更高级别的操作,例如用于实现增量的compareAndSwap。
AtomicXXXX还支持Lazyset。这就像一个易失性集,但不会延迟管道等待写入完成。这可能意味着,如果你读一个值,你只需写,你可能会看到旧的值,但无论如何你不应该这样做。不同的是,设置一个易失性大约需要5纳秒,而位Lazyset大约需要0.5纳秒。