CAS非左塞同步算法

在java并发编程里要实现原子操做,你们都会想到同步(synchronize),这种同步会使线程左塞,在性能上不是很满意。基于CAS(Compare And Set) 能够实现非左塞同步算法。 java

何为cas? 算法

compare-and-swap (CAS) is an atomic instruction used in multithreading to achieve synchronization

简单来讲就是原子操做,系统支不支持CAS还要看cpu,如今几乎全部的CPU指令都支持CAS的原子操做,X86下对应的是 CMPXCHG 汇编指令。cas指令须要三个操做数,非别是内存位置(V),旧值预期值(A)和新值。cas指令执行时,当且仅当V符合旧预期值A是,处理器用新的值B更新V的值,不然不执行更新。 编程

jdk1.5为咱们提供java.util.concurrent并发包,提供很方便的原子操做类,底层实现由sun.misc.Unsaft类里的compareAndWapInt和compareAndLong等几个方法封装调用,注意sun.misc.Unsaft是非标准的java api api

非阻塞的计数器 多线程

使用AtomicInteger的compareAndSet方法,很是简单实现非左塞的计数器,代码比用同步块实现多线程的计数器简单的多。 并发


public class NonblockingCounter {
    private AtomicInteger value;
    public int getValue() {
        return value.get();
    }
    public int increment() {
        int v;
        do {
            v = value.get();
        while (!value.compareAndSet(v, v + 1));
        return v + 1;
    }
}

compareAndSet在一个死循环中,不断尝试将一个比当前值大1 赋值给本身,若是执行失败,说明有其余线程修改了值,只要从新循环执行一次操做,直到成功为止。  性能

非阻塞的简单链表 this

使用AtomicReference实现一个简单的链表操做(add),整体类结构和普通的链表差很少。 atom


public class ConcurrentLinked<E> {

	private AtomicReference<Node<E>> first = new AtomicReference<Node<E>>();

	public boolean add(E e) {
		

		Node<E> n = new Node<E>(e);

		while (first.get() == null && first.compareAndSet(null, n)) {
			return true;
		}

		for (;;) {
			Node<E> insertNode = findInsertionPlace();

			if (insertNode.next.compareAndSet(null, n)) {
				break;
			}
		}

		return true;
	}


	public E getLast() {
		Node<E> a = getFirstNode();

		if (a == null)
			return null;

		while (a.next.get() != null) { // 找插入位置
			a = a.next.get();
		}
		return a.item;
	}

	private Node<E> getFirstNode() {
		return this.first.get();
	}

	private Node<E> findInsertionPlace() {
		Node<E> a = getFirstNode();

		while (a.next.get() != null) { // 找插入位置
			a = a.next.get();
		}

		return a;
	}

	private static class Node<E> {

		E item;

		AtomicReference<Node<E>> next = new AtomicReference<Node<E>>();

		public Node(E item) {
			this.item = item;
		}
	}


}




cas看似很完美,可是不是全部的原子操做场景都适合,好比,多个变量同步原子更新。使用cas的地方,通常会把compareAndSet放到一个无限的循环中,在线程竞争比较激烈的状况下,cpu消耗比较严重的。另外,cas自己有一个逻辑漏洞(俗称"ABA"问题)。 spa


参考资料

《java并发编程实践》

相关文章
相关标签/搜索