《Java并发编程实战》笔记-非阻塞算法
如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败和挂起,那么这种算法就被称为非阻塞算法。如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法。如果在算法中仅将CAS用于协调线程之间的操作,并且能正确地实现,那么它既是一种无阻塞算法,又是一种无锁算法。
创建非阻塞算法的关键在于,找出如何将原子修改的范围缩小到单个变量上,同时还要维护数据的一致性。
非阻塞算法的所有特性:某项工作的完成具有不确定性,必须重新执行。
复杂数据结构的非阻塞算法,如非阻塞链接队列,因为它必须支持对头节点和尾节点的快速访问,因此它需要单独维护头指针和尾指针。插入新元素时需要采用两个原子操作更新当前最后元素指针和尾指针,这会使队列处于不一致状态。我们需要使用一些技巧,第一是,即使在一个包含多个步骤的更新操作中,也要确保数据结构总是处于一致状态。第二是,如果当B到达时发现A正在修改数据结构,那么在数据结构中就应该有足够的信息,使得B能完成A的更新操作。
Michael-Scott(Michael and Scott,1996)非阻塞算法中的插入算法
package net.jcip.examples; import java.util.concurrent.atomic.*; import net.jcip.annotations.*; /**
* LinkedQueue
* <p/>
* Insertion in the Michael-Scott nonblocking queue algorithm
*
* @author Brian Goetz and Tim Peierls
*/
@ThreadSafe
public class LinkedQueue <E> { private static class Node <E> {
final E item;
final AtomicReference<LinkedQueue.Node<E>> next; public Node(E item, LinkedQueue.Node<E> next) {
this.item = item;
this.next = new AtomicReference<LinkedQueue.Node<E>>(next);
}
} private final LinkedQueue.Node<E> dummy = new LinkedQueue.Node<E>(null, null);
private final AtomicReference<LinkedQueue.Node<E>> head
= new AtomicReference<LinkedQueue.Node<E>>(dummy);
private final AtomicReference<LinkedQueue.Node<E>> tail
= new AtomicReference<LinkedQueue.Node<E>>(dummy); public boolean put(E item) {
LinkedQueue.Node<E> newNode = new LinkedQueue.Node<E>(item, null);
while (true) {
LinkedQueue.Node<E> curTail = tail.get();
LinkedQueue.Node<E> tailNext = curTail.next.get();
if (curTail == tail.get()) {
if (tailNext != null) {
// Queue in intermediate state, advance tail
tail.compareAndSet(curTail, tailNext);
} else {
// In quiescent state, try inserting new node
if (curTail.next.compareAndSet(null, newNode)) {
// Insertion succeeded, try advancing tail
tail.compareAndSet(curTail, newNode);
return true;
}
}
}
}
}
}
ABA问题,在某些算法中,如果V的值首先由A变成B,再由B变成A,那么仍然被认为是发生了变化,并需要重新执行算法中的某些步骤。Java类库提供AtomicStampedReferencet和AtomicMarkableReference处理ABA问题。AtomicStampedReferencet将更新一个“对象-引用”二元组,通过在引用上加上“版本号”,从而避免ABA问题。AtomicMarkableReference将更新一个“对象引用-布尔值”二元组,在某些算法中将通过这种二元组使节点保存在链表中同时又将其标记为“已删除的节点”。
《Java并发编程实战》笔记-非阻塞算法的更多相关文章
- Java并发编程实战.笔记十一(非阻塞同步机制)
关于非阻塞算法CAS. 比较并交换CAS:CAS包含了3个操作数---需要读写的内存位置V,进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不 ...
- 29、Java并发性和多线程-非阻塞算法
以下内容转自http://ifeve.com/non-blocking-algorithms/: 在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在 ...
- 多线程-java并发编程实战笔记
线程安全性 编写线程安全的代码实质上就是管理对状态的访问,而且通常都是共享的,可变的状态. 一个对象的状态就是他的数据,存储在状态变量中,比如实例域或静态域.所谓共享是指一个对象可以被多个线程访问:所 ...
- Java并发编程实战笔记—— 并发编程1
1.如何创建并运行java线程 创建一个线程可以继承java的Thread类,或者实现Runnabe接口. public class thread { static class MyThread1 e ...
- Java并发编程实战笔记
如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误.有三种方式可以修复这个问题: i.不在线程之间共享该状态变量 ii.将状态变量修改为不可变的变量 iii.在访问状态变 ...
- java并发编程实战笔记---(第五章)基础构建模块
. 5.1同步容器类 1.同步容器类的问题 复合操作,加容器内置锁 2.迭代器与concurrentModificationException 迭代容器用iterator, 迭代过程中,如果有其他线程 ...
- java并发编程实战笔记---(第三章)对象的共享
3.1 可见性 synchronized 不仅实现了原子性操作或者确定了临界区,而且确保内存可见性. *****必须在同步中才能保证:当一个线程修改了对象状态之后,另一个线程可以看到发生的状态变化. ...
- java并发编程实战笔记---(第四章)对象的组合
4.1设计线程安全的类 包含三个基本要素: 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 2.简历对象状态的并发访问管理策略 对象的状态: 域 基本类型所有域, 引用类型包括被引用 ...
- Java并发编程实战笔记—— 并发编程4
1.同步容器类 同步容器类都是线程安全的,但在某些情况下可能需要额外的客户端加锁保护复合操作. 容器上常见的复合操作包括但不限于:迭代(反复访问数据,直到遍历完容器中所有的元素为止).跳转(根据指定顺 ...
- Java并发编程实战笔记—— 并发编程2
1.ThreadLocal Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作.因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有一个指向同一个ThreadL ...
随机推荐
- PTA——最大公约数和最小公倍数
PTA 7-26 最大公约数和最小公倍数 #include<stdio.h> int main(){ int num1,num2,temp1,temp2,r; scanf("%d ...
- c# 敏捷2 ForEach ToDictionary ToLookup Except比较
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; ...
- mysqldump命令之single-transaction
=========================================================在mysqldump中指定single-transaction时,会使用可重复读(RE ...
- hasura graphql-engine &&patroni docker-compose 环境运行
patroni 是一个很不错的pg ha 解决方案,graphql-engine 是一个很好的graphql 工具,为了方便使用 参考patroni官方的文档,使用docker-compose 将应用 ...
- Winform里面的缓存,MemoryCache使用
缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力.本文主要针对自己在Winform方面的缓存使用做一个引导性的介绍,希望大家能够从中了解一些缓存 ...
- Oracle sqlnet.ora配置
Oracle sqlnet.ora配置 sqlnet.ora的作用(官网指出的) www.2cto.com 1.限制客户端访问(如指定客户端域为不允许访问) 2.指定命名方法(local nami ...
- Pycharm主题设置以及导入方式
主题下载链接: http://www.themesmap.com/ pycharm -- 导入主题(theme) and 修改背景颜色(护眼色) 前情提要 众所周知,随着python语言的不断流行 ...
- Wireshark常用过滤使用方法
过滤源ip.目的ip. 在wireshark的过滤规则框Filter中输入过滤条件.如查找目的地址为192.168.101.8的包,ip.dst==192.168.101.8:查找源地址为ip.src ...
- 一个简单的web.py论坛
一.概述 forum是一个简单的web.py论坛,后端采用Python+web.py+MySQL,前端采用HTML+CSS+JavaScript+jQuery+RequireJS. 该论坛的主要功能包 ...
- Git安装及密钥的生成(转)
1.下载Git软件:http://msysgit.github.io/ 2.安装git软件(很简单).安装成功后,在[开始]->[程序]->[git],下就会看见Git Bash和Git ...