[JAVA学习笔记-75]关于CAS

来源:互联网 发布:文言文乎的用法 编辑:程序博客网 时间:2024/06/07 20:38

Compare and swap
CAS即比较并交换,目前处理器在指令集中予以支持。换句话说,对于应用程序开发来说,并不直接使用CAS方法,而是使用特定的接口来使用。
以JAVA为例,CAS被封装在原子对象中,如AtomicInteger,如果调用其incrementAndGet()方法,则方法内部通过unsafe调用底层操作系统+汇编
指令执行CAS。
还是以JAVA为例,AtomicXXX族的引入避免了在对primitive types进行增减操作时需要用到synchronized,reentrantLock等重型的同步方式,而
volatile本身无法保证原子性(volatile只能保证多线程可见性,但是对volatile变量的运算操作,非原子操作,如i++)

//使用volatile
public class MyApp
{
private volatile int count = 0;
public void upateVisitors()
{
++count; //increment the visitors count
}
}

//使用常规同步(对象锁)
public class MyApp
{
private int count = 0;
public synchronized void upateVisitors()
{
++count; //increment the visitors count
}
}

//使用AtomicInteger
public class MyApp
{
private AtomicInteger count = new AtomicInteger(0);
public void upateVisitors()
{
count.incrementAndGet(); //increment the visitors count
}
}

public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}

适用性:
Using synchronised is more efficient if you expect to be waiting a long time (e.g. milli-seconds) as the thread can fall asleep and release the CPU to do other work.
【synchronised使用方便,如果线程等待时间较长,使用这种方式更好。】

Using compareAndSwap is more efficient if you expect the operation to happen quite quickly. This is because it is a simple machine code instruction and take as little as 10 ns. However if a resources is heavily contented this instruction must busy wait and if it cannot obtain the value it needs, it can consume the CPU busily until it does.
【如果同步操作非常短小(时间短,代码规模小),则适合用CAS机制的AtomicXXX族对象。但是如果资源争夺较激烈,可能造成CPU资源浪费(CAS的本质
是循环比较并等待,如果一个线程长时间获取不到目标对象,会一直循环比较。而对象锁的方式线程可以sleep释放CPU。)
简述:
传统对象锁的同步方式适合体量比较大,同步效率要求不是特别高的场景;CAS适合同步操作短小精悍,但资源竞争不是特别激烈的场景。】

If you use off heap memory, you can control the layout of the data being shared and avoid false sharing (where the same cache line is being updated by more than one CPU). This is important when you have multiple values you might want to update independently. e.g. for a ring buffer.

Note: synchronized is implemented using a compareAndSwap and much more besides and has to do work on obtaining the lock and releasing it.

注:
1、AtomicInteger的set方法,直接对value赋值,因为value是volatile变量,所以自动保证多线程的可见性。
2、Set方法与getAndSet为什么在实现上有区别,后者为什么要用compareAndSet而不是直接赋值?

原创粉丝点击