首页 > 代码库 > lcok-free简易实现

lcok-free简易实现

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 =http://www.mamicode.com/ 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.退出

lcok-free简易实现