标签:style blog color io ar java for sp div
lock-free是一种基于原子变量类来构建的非阻塞同步算法。
比较并交换(compare-and-swap)
我们经常会先检查某项东西,然后对其进行修改,如if(X...) {X=...}。这种行为在多线程下并不是线程安全的。那我们该如何做呢?
一种方法是对操作进行加锁,如
synchornized(obj){
if(x>0){
x -= 10;
}
}
究其原因,是因为上面的操作是一个复合操作。我们是否可以通过某种不可分的方式来处理呢?...
几乎所有的现代处理器都包含了比较并交换(CAS)指令。CAS包含了3个操作数--需要读写内存的位置V、进行比较的值A和拟写入的新值,当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不会执行任何操作。通过CAS我们可以把这种“先检查后执行”行为作为一个不可分的整体来处理。在Java1.5之后,原子变量类中提供了这种操作。
下面写个简单取钱的例子,看看其在Java下的应用。账户有一定的余额(10000),在多线程下每个人一次可取4000。如果写的withDraw(long)线程不安全,则可能余额被减成负数。
public class AccountCAS extends Thread{ private Account account; public AccountCAS(Account account){ super(); this.account = account; } @Override public void run() { try { Thread.sleep(500); account.withDraw(4000); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final int NUM = 5; Account ac = new Account(); for(int i=0;i<NUM;++i){ new AccountCAS(ac).start(); } } } class Account{ /** * 余额 */ private AtomicLong balance = new AtomicLong(10000); public void withDraw(long money){ long oldValue = balance.get(); if(oldValue>=money){ while(true){ if(balance.compareAndSet(oldValue, oldValue-money)){ System.out.println(Thread.currentThread().getName()+" withDraw:"+money); break; } } } } }
运行结果如下:
Thread-0 withDraw:4000
Thread-3 withDraw:4000
以上的Lock-free算法不需要加锁,通常包含以下几点:1.原子变量 2.循环 3.CAS 4.退出
标签:style blog color io ar java for sp div
原文地址:http://www.cnblogs.com/dreamysmurf/p/4009110.html