[英]Using compareAndSet for Thread safety
以下演示代码如何线程安全? 我们确保在CAS指令中是否未修改该值,然后对int进行递增。 不return v + 1;
超越了整个目标,因为它可以跳过线程更新。
此处,原子整数用于模拟无阻塞的int计数器。
//Here value is an atomic integer
public int increment()
{
int v;
for(;;)
{
v = value.get();
if(value.compareAndSet(v, v + 1))
return v + 1;
}
}
代码不应该是这样的:
public int increment()
{
int v;
for(;;)
{
v = value.get();
if(value.compareAndSet(v, v + 1))
return value.get();
}
}
如果当前值等于期望值v
,则compareAndSet()
返回true
,因此该值已更新为v + 1
。
在您的第一个版本中,如果两个线程都获得相同的初始值,则一个线程将成功(更新为v + 1
),另一个线程将失败(因为当前值不再是v
),然后使用v + 1
和v + 2
重试。
如果此代码旨在返回唯一键,则第一个版本是正确的,因为在compareAndSet()
返回true
的点,当前值保证为v + 1
(即使只是短暂的)。 如果另一个线程修改了对compareAndSet()
和get()
调用之间的值,则第二个版本可能会由于竞争条件而返回重复的值。
就是说,您可能想研究AtomicInteger
incrementAndGet()
方法,该方法执行几乎相同的操作,但效率更高(没有显式循环)。
定义“工作”。
假设value
最初为零。 如果第一个函数被调用100次,它将在1到100之间的每个数字恰好返回一次。 第二个函数没有此属性。
到函数返回时,这两个函数都可以生成过期的值。
哪个更“正确”确实取决于increment
的预期语义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.