Java – Compare and Swap 和 synchronized 块

huangapple go评论59阅读模式
英文:

Java - Compare and Swap and synchronized Block

问题

public class SimulatedCAS {
  private int value;

  public synchronized int get() { return value; }

  public synchronized int compareAndSwap(int expectedValue, int newValue) {
    int oldValue = value;
    if (oldValue == expectedValue)
        value = newValue;
    return oldValue;
  }
}

public class CasCounter {
  private SimulatedCAS value;

  public int getValue() {
    return value.get();
  }

  public int increment() {
    int v = value.get();
    while (v != value.compareAndSwap(v, v + 1)) {
      v = value.get();
    }
  }
}

我参考了一本名为《Java Concurrency in Practice》的书籍。一个计数器必须能够被多个线程增加。我尝试使用比较和交换方法,但最终它还是使用了synchronized关键字,这可能会导致线程的阻塞和等待。使用synchronized块提供了与我相同的性能,是否有人能说明一下使用比较和交换与使用synchronized块之间的区别?或者有没有其他方法可以在不使用synchronized块的情况下实现比较和交换?

英文:
public class SimulatedCAS { 
  private int value;

  public synchronized int get() { return value; }

  public synchronized int compareAndSwap(int expectedValue, int newValue) 
  {
  int oldValue = value; 
  if (oldValue == expectedValue) 
      value = newValue;
  return oldValue; 
  }
}

public class CasCounter 
{ 
   private SimulatedCAS value;

   public int getValue() 
   { 
     return value.get();
   }
  
  public int increment() 
  { 
      int value.get(); 
      while (v != value.compareAndSwap(v, v + 1)) 
      {
         v = value.get(); 
      }
  }

}

I refereed a Book "Java Concurrency in Practice"

a Counter must be increased by multiple threads. I tried using the compare and swap method but at the end it make used of synchronized keyword which might again result in blocking and waiting of threads. using a synchronized block provides me the same performance can anybody state. what is the difference between using compare and swap and synchronized block ? or any other way to implement compare and swap without using synchronized block.

答案1

得分: 1

AtomicInteger适用于这种情况。

您可以使用final AtomicInteger i=new AtomicInteger(initial_value);来创建它。然后,您可以调用i.set(new_value)来设置它的值,还可以调用i.get()来获取它的值,对于您的应用程序最重要的是,您可以调用i.incrementAndGet()来以原子方式增加该值。

如果N个不同的线程同时调用i.incrementAndGet(),那么

  • 每个线程都保证看到不同的返回值,以及
  • 在它们都完成后,最终值保证增加了确切的N。

AtomicInteger类还有相当多其他方法。大多数方法对多个线程访问变量时发生的情况提供有用的保证。

英文:

> I need to increment counter with multiple threads

The AtomicInteger class is good for that.

You can create it with final AtomicInteger i=new AtomicInteger(initial_value); Then you can call i.set(new_value) to set its value, and you can call i.get() to get its value, and most importantly for your application, you can call i.incrementAndGet() to atomically increment the value.

If N different threads all call i.incrementAndGet() at "the same time," then

  • Each thread is guaranteed to see a different return value, and
  • The final value after they're all done is guaranteed to increase by exactly N.

The AtomicInteger class has quite a few other methods as well. Most of them make useful guarantees about what happens when multiple threads access the varaible.

答案2

得分: 0

真正的比较和交换采用了乐观锁定。它先改变值,然后如果有同时改变变量的情况发生,就会回滚。因此,如果变量很少被修改,那么CAS的性能要优于同步。

但如果变量经常被修改,那么同步的性能更好,因为它不允许在变量被改变时干扰它。因此,不需要进行昂贵的回滚操作。

英文:

Real Compare and Swap does optimistic locking. It changes value and then makes a rollback if something has changed the variable simultaneously. So, if the variable is modified rarely, then CAS performs better, than synchronized.

But if the variable is modified often, then synchronized performs better, because it doesn't allow anything to mess with the variable while it is changed. And so there's no need to make an expensive rollback.

huangapple
  • 本文由 发表于 2020年7月21日 18:50:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/63012900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定