对于CAS是一种有别于synchronized的一种乐观锁实现.是一种非阻塞锁算法.CAS通过与原始预期值进行比较来确定是否修改主内存中数据的一种方案.基于一个线程的失败或者挂起不应该影响其他线程的失败或挂起这样的前提,而提出硬件层次的实现数据处理的互斥。可以自动更新共享数据,而且能够检测到其他线程的干扰,而
compareAndSet() 就用这些代替了锁定。对于实现CAS的原子类(AtomicInteger等)不仅仅对于单个贡献变量保证了原子性,同时借助volatile变量让共享变量保持可见性.,那么对于单个共享变量而言是可以实现线程安全的通信的,是不需要阻塞的同步方式比如synchronized实现同步。
下面我们通过一个例子来学习银行多线程并发取钱的实例.
1.单共享变量操作类
public class AtmicCounter {
private AtomicLong balance;
public AtmicCounter(long money)
{
balance=new AtomicLong(money);
System.out.println("当前金额--->"+balance);
}
//存钱
public void deposit(long money)
{
balance.addAndGet(money);
}
//取钱(取money这么多钱)
public void withDraw(long money)
{
//取得当前值
long oldValue=this.balance.get();
if(oldValue>0)
{
try {
Thread.sleep(10);
if(this.balance.compareAndSet(oldValue, oldValue-money))
{
System.out.println(Thread.currentThread().getName()+" withDraw "+oldValue +" successful!!");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.测试类
public class AtomicCounterTest extends Thread{
private AtmicCounter counter;
public AtomicCounterTest(AtmicCounter counter)
{
this.counter=counter;
}
public void run()
{
while(true){
this.counter.withDraw(1);
}
}
/**
* 银行取钱测试
*/
public static void main(String[] args) {
AtmicCounter counter=new AtmicCounter(100);
AtomicCounterTest test1=new AtomicCounterTest(counter);
AtomicCounterTest test2=new AtomicCounterTest(counter);
AtomicCounterTest test3=new AtomicCounterTest(counter);
AtomicCounterTest test4=new AtomicCounterTest(counter);
test1.start();
test2.start();
test3.start();
test4.start();
}
}
小结:对于单变量情况可以通过原子类保证线程安全,但是多个共享变量不能保证.
原子类通过(CAS和volatile)实现单共享变量的线程安全