Java AtomicInteger类有一个方法 -
boolean weakCompareAndSet(int expect,int update)
Run Code Online (Sandbox Code Playgroud)
它的文件说:
可能是虚假的失败.
这里"虚假失败"的意思是什么?
Von*_*onC 18
虚假地:没有明显的理由
根据atomic包javadoc:
原子类还支持weakCompareAndSet方法,其适用性有限.
在某些平台上,弱版本可能比普通情况下的compareAndSet更有效,但不同之处在于,任何给定的weakCompareAndSet方法调用都可能虚假地返回false(也就是说,没有明显的原因).
错误返回仅表示如果需要可以重试操作,依赖于当变量保持expectedValue时没有其他线程也尝试设置变量的重复调用的保证最终会成功.
(例如,这种虚假故障可能是由于与预期值和当前值相等无关的内存争用效应.)另外,weakCompareAndSet不提供同步控制通常需要的排序保证.
根据这个线程,它不是因为"硬件/操作系统",而是因为weakCompareAndSet使用的底层算法:
如果当前值==期望值,则weakCompareAndSet以原子方式将值设置为给定的更新值.可能是虚假的失败.
与compareAndSet()和AtomicX上的其他操作不同,weakCompareAndSet()操作不会创建任何先前发生的排序.
因此,仅仅因为线程看到由weakCompareAndSet引起的对AtomicX的更新并不意味着它与weakCompareAndSet()之前发生的操作正确同步.
您可能不想使用此方法,而应该只使用compareAndSet; 因为很少有情况下weakCompareAndSet比compareAndSet快,并且在许多情况下,尝试使用weakCompareAndSet而不是compareAndSet来优化代码会导致细微且难以在代码中重现同步错误.
有关发生前的订单的注意事项:
Java内存模型(JMM)定义了读取变量的线程保证在另一个线程中看到写入结果的条件.
JMM定义了一个名为happen-before的程序操作的顺序.
发生在线程之前的排序只能通过同步公共锁或访问公共volatile变量来创建.
在没有事先排序的情况下,Java平台有很大的自由度来延迟或改变一个线程中的写入在另一个线程中读取同一个变量的可见顺序.
这意味着即使它当前包含期望值,它也可能返回false(并且不会设置新值).
换句话说,该方法可能无所作为,并且没有明显的原因返回false ...
有一些CPU体系结构可能具有强大的性能优势CompareAndSet().
关于为什么会发生这样的事情的更具体细节.
某些体系结构(如较新的ARM)使用加载链接(LL)/存储条件(SC)指令集实现CAS操作.LL指令将值加载到内存位置并在某处"记住"该地址.如果尚未修改记住地址处的值,则SC指令将值存储到该存储器位置.硬件有可能认为该位置已经被修改,即使它显然没有多种可能的原因(原因可能因CPU架构而异):
小智 6
weakCompareAndSet的一个很好的用例是性能计数器 - 无需订购,更高的更新率(因此在弱序系统上排序会受到伤害),但不会在高负载下丢弃计数(严格满足的性能计数器可能会下降99%)计数,基本上将计数器的值相对于非竞争计数器随机保留.
| 归档时间: |
|
| 查看次数: |
3776 次 |
| 最近记录: |