繁体   English   中英

使用compareAndSet保证线程安全

[英]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 + 1v + 2重试。

如果此代码旨在返回唯一键,则第一个版本是正确的,因为在compareAndSet()返回true的点,当前值保证为v + 1 (即使只是短暂的)。 如果另一个线程修改了对compareAndSet()get()调用之间的值,则第二个版本可能会由于竞争条件而返回重复的值。

就是说,您可能想研究AtomicInteger incrementAndGet()方法,该方法执行几乎相同的操作,但效率更高(没有显式循环)。

定义“工作”。

假设value最初为零。 如果第一个函数被调用100次,它将在1到100之间的每个数字恰好返回一次。 第二个函数没有此属性。

到函数返回时,这两个函数都可以生成过期的值。

哪个更“正确”确实取决于increment的预期语义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM