Java并发编程中的非阻塞算法是指那些在执行过程中不会导致线程长时间等待的设计。这类算法通常基于CAS(比较并交换,Compare-and-Swap)操作或乐观锁机制实现,并用于构建非阻塞的并发数据结构。
-
非阻塞并发数据结构:
这些数据结构如无锁栈、无锁队列、无锁哈希表等,在不使用传统的互斥锁的情况下,通过原子操作(如CAS)实现多线程间的同步与协作,从而避免了线程上下文切换和阻塞带来的性能开销。 -
比较交换(CAS):
CAS是硬件级别支持的一种原子指令,它同时检查并更新内存位置的值。在Java中,java.util.concurrent.atomic
包下的原子类(如AtomicInteger、AtomicLong等)就利用了CAS来实现线程安全的数据修改。在执行CAS时,会先读取当前值并与预期值进行比较,如果一致则更新为新值,否则不作任何改动。 -
乐观锁:
乐观锁是一种假设多线程并发访问冲突概率较低的策略。它在读取数据时不加锁,但在更新数据前会先判断该数据自上次读取后是否被其他线程修改过。在Java中,乐观锁可以通过CAS操作或者版本号等方式实现。 -
共享意向修改:
在非阻塞算法中,多个线程可能试图对同一个数据进行修改,为了确保数据的一致性,需要采用“共享意向修改”的方式,即每个线程在修改数据之前先获取一个副本,然后在本地完成修改,最后通过CAS操作将修改后的结果写回共享数据。 -
ABA问题:
非阻塞算法中常见的一个问题就是ABA问题,即一个变量从A变为B再变回A,而单纯依赖CAS操作可能无法察觉这个过程。解决ABA问题的方法通常是在每次修改时增加版本号或者序列号,使得每次修改都有唯一标识。 -
非阻塞算法模板:
Michael & Scott提出的非阻塞算法模板是一个通用框架,可以用来构建许多非阻塞数据结构,例如无锁栈。该模板利用了CAS操作以及一种名为“Treiber栈”的数据结构,实现了在没有锁定的情况下对栈进行并发操作。在这个模板中,节点之间形成链表结构,每个线程尝试入栈或出栈时都会先检查栈顶元素的状态,然后通过CAS操作更新栈顶指针。即使竞争失败,也不会阻塞而是继续重试。