cas算法及其可能存在的问题(cas算法原理)

上海园区招商办公室

联系人:梁经理

联系电话:15000456391

欢迎来电咨询,竭诚为你服务!


鉴于本人对知识理解的深度有限,且尚需更多地学习,如有错误和不足欢迎指正批评。

为了在并发编程中保证线程安全,通常我们会对某个资源进行上锁。如果发生多个线程同时操作一个资源,那么只有拿到资源对应锁的一个或多个线程可以对该资源进行操作,其余线程都将陷入一种等待资源的阻塞状态当中。

如果拿到锁的线程由于一些I/O操作、或内存缺页、或超时网络请求等情况,那么很可能会出现所有需要锁资源的线程都不能继续执行下去。

因此,在基于锁的算法中可能会发生各种活跃性故障。

非阻塞?无锁?

  1. 如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败或挂起,那么这种算法就被称为非阻塞算法。
  2. 如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法。
  3. 如果在算法中仅将CAS用于协调线程之间的操作,并且能正确地实现,那么它既是一种无阻塞算法,又是一种无锁算法。

在非阻塞的算法中,不会存在死锁,但却可能会存在活锁

活锁:当线程获取锁失败之后会最终返回,不会始终阻塞,且在失败后反复重试。像这种反复获取锁、且最终获取不到的情况,一般被称为活锁。

非阻塞的栈

使用Treiber算法(Treiber, 1986)构造的非阻塞栈

public class ConcurrentStack<E> {
    AtomicReference<Node<E>> top = new AtomicReference<Node<E>>();

    public void push(E item) {
        Node<E> newHead = new Node<E>(item);
        Node<E> oldHead;
        do {
            oldHead = top.get();
            newHead.next = oldHead;
        } while (!top.compareAndSet(oldHead, newHead));
    }

    public E pop() {
        Node<E> oldHead;
        Node<E> newHead;
        do {
            oldHead = top.get();
            if (oldHead == null) return null;
            newHead = oldHead.next;
        } while (!top.compareAndSet(oldHead, newHead));
        return oldHead.item;
    }

    private static class Node<E> {
        public final E item;
        public Node<E> next;

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

CAS提供线程安全的根本原因

ConcurrentStack能够保证线程安全,或者说CAS能够保证线程安全的根本原因在于,在CAS的底层不仅提供了原子性,还提供了可见性。

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 792114587@qq.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.qiked.com/6939.html