使用compareAndSet进行线程安全

Jyo*_*rge 0 java multithreading

以下演示代码如何线程安全?我们确保是否在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;   
   }
}
Run Code Online (Sandbox Code Playgroud)

代码不应该是这样的:

public int increment() 
{
   int v;
   for(;;) 
   {
      v = value.get();
      if(value.compareAndSet(v, v + 1))
         return value.get();   
   }
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*onJ 5

compareAndSet()返回true如果当前值等于预期值v,因而值进行了更新,v + 1.

在您的第一个版本中,如果两个线程获得相同的初始值,则一个将成功(更新到v + 1),另一个将失败(因为当前值不再v),并使用v + 1和重试v + 2.

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

也就是说,你可能想调查一下AtomicInteger这个incrementAndGet()方法,这个方法几乎完全相同,但效率更高(没有明确的循环).