笔记_并发编程实践_十五
来源:互联网 发布:淘宝开店要押金吗 编辑:程序博客网 时间:2024/06/05 19:14
原子变量与非阻塞同步机制
1.锁的劣势:
(1)需然jvm对非竞争的锁的获取和释放优化至非常高效,但是但该锁频繁地繁盛竞争时。调度与真正用于工作的开小间的比值会很可观。2.硬件对并发的支持
(2)优先级倒置问题,当低优先级的线程持有锁,并发生任何延迟,高优先级的线程都不会被执行。
(1底层处理器具有原子化的“测试并设置”,“获取并增加”以及“交换”指令,现代的处理器具有一些原子化的读-改-写操作,如“比较并交换”,“加载链接/存储条件”3.比较锁和原子变量
但是在jdk5以前,这些还不能直接为java类所用
(2)比较并交换:<1>比较并交换式一项乐观锁技术,意思是:“我认为v的值应该是a,如果是则赋值b,如果不是,则返回v的值”
<2>cas比锁更高效,但是更复杂
<3>原子变量AtomicXX都提供compareAndSet方法(域更新器的comapareAndSet同样可以实现)
(1)在中低竞争的情况下原子变量的性能比较好,在高强度竞争下,锁能够很好地避免竞争(由于compareAndSet实现的原子变量,类似于乐观锁,会在设置失败后重新设置,在高强度竞争下会导致更多的竞争)4.非阻塞算法
(1)构建非阻塞算法的窍门是:缩小原子化的非为到唯一的变量(该变量使用原子变量AutomicXX,利用其CompareAndSet方法“投机地”更新值这一最基本的模式)5.一些练习:(注意,若向使用类似的容器应该使用jdk提供的,只是练习compareAndSet)
(2)非阻塞链表,队列,原子化的域更新器的实现
(3)原子化的域更新器:<1>更新器类没有构造函数,通过newUpdater的工厂方法,生命类的和域的名称(4)ABA问题:
<2>提供较弱的原子性,只能保证通过与更新器去更新域时原子操作,但是通过其他途径可以修改该属性(1)这是compareAndSet无用引起的反常现象,主要存在于不能被垃圾回收的环境中,也就是当compare一部的时候,比较到当前值是否为A时,可能A已经转换为B在转换为A,在这一情况下肯能使得compareAndSeet同样成功。
(2)简单的解决方法,更新一对值而不是一个值,即引用版本号,那么即使a改为b后再改为a,版本号也是不同的。
(3)AtomicStampedReference和AtomicMarkableReference提供了一对变量原子化的条件更新。
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package TestConcurrent;import java.util.ArrayList;import java.util.List;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.atomic.AtomicReference;import java.util.logging.Level;import java.util.logging.Logger;/** * 尝试使用原子变量的compareAndSet实现同步的堆栈 注意一点CAS对比锁的使用,在中低级的竞争环境下可以提供更高的效率 * */public class TestConcurrentStack {//使用AtomicReference、构建Node类型的原子变量,代表当前栈顶 AtomicReference<Node> top = new AtomicReference<Node>(); public TestConcurrentStack() { top.set(new Node()); } public void push(Object value) { //获得当前top值以使用cas Node oldHead; Node newHead; do { oldHead = top.get(); newHead = new Node(oldHead, value); } while (!top.compareAndSet(oldHead, newHead)); } public Object pop() { Node oldHead; Node newHead = null; Boolean result = false; do { oldHead = top.get(); if (oldHead == null || oldHead.next == null) { try { Thread.sleep(Double.valueOf(Math.random() * 1000).longValue()); continue; } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } newHead = oldHead.next; result = top.compareAndSet(oldHead, newHead); } while (!result); return oldHead.value; } public static void main(String args[]) { TestConcurrentStack stack = new TestConcurrentStack(); CyclicBarrier barrier = new CyclicBarrier(1000);//保证线程同一时间起跑 List<Thread> list = new ArrayList(); for (int i = 0; i < 510; i++) { Thread t = new Thread(new pusher(stack, barrier)); list.add(t); t.start(); } for (int i = 0; i < 490; i++) { Thread t = new Thread(new poper(stack, barrier)); list.add(t); t.start(); } for (Thread t : list) { try { t.join(); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } System.out.println("-------以下将打印出当前堆栈中的各个对象-----"); Node curNode = stack.top.get(); int i = 0; while (curNode != null) { System.out.println("【" + curNode.value + "】"); curNode = curNode.next; i++; } System.out.println("------------------栈中还有【" + i + "】个数据----------------------"); } public static class pusher implements Runnable { TestConcurrentStack stack; CyclicBarrier barrier; public pusher(TestConcurrentStack stack, CyclicBarrier barrier) { this.stack = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); this.stack.push(Thread.currentThread().getName() + "插入数据"); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } } public static class poper implements Runnable { TestConcurrentStack stack; CyclicBarrier barrier; public poper(TestConcurrentStack stack, CyclicBarrier barrier) { this.stack = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); Object value = this.stack.pop(); if (value != null) { System.out.println(Thread.currentThread().getName() + "删除了数据【" + value + "】"); } else {// System.out.println(Thread.currentThread().getName() + "当前栈顶为空 【 】 "); } } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } } /** * 代表节点 */ public static class Node { public Node next; public Object value; public Node() { } public Node(Node next, Object value) { this.next = next; this.value = value; } @Override public boolean equals(Object obj) { if (obj instanceof Node && value != null) { return value.equals(((Node) obj).value); } return false; } }}
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package TestConcurrent;import java.util.ArrayList;import java.util.List;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.atomic.AtomicReference;import java.util.logging.Level;import java.util.logging.Logger;/** * 尝试用CompareAndSet实现队列 关于队列的队尾,在队尾插入数据,有两步,1.把元队尾队元素指向新队尾元素 2.把队尾指针改为指向新插入元素 * 由于分两步,所以不能直接使用cas来实现,又因为执行第一步后队尾指针指向的元素不在是队尾元素(该元素不指向null),所以可以其他线程可以判断 */public class TestConcurrentQueue {//使用AtomicReference、构建Node类型的原子变量,代表当前栈顶 Node dummy = new Node(); AtomicReference<Node> head = new AtomicReference<Node>(); AtomicReference<Node> tail = new AtomicReference<Node>(); public TestConcurrentQueue() { AtomicReference<Node> tem = new AtomicReference<Node>(dummy); head.set(new Node(tem, "")); tail.set(new Node(tem, "")); } public void push(Object value) { while (true) { Node curTail = tail.get(); Node tailNext = curTail.next.get(); if (tailNext != null) {//处于中间状态 //帮助执行吧队尾指针指向现在队尾的工作 tail.compareAndSet(curTail, tailNext); } else {//静止状态 curTail.next.compareAndSet(null, new Node(null, value)); tail.compareAndSet(curTail, tailNext); return; } } } public Object pop() {//当删除的是最后一个元素,与插入并发执行时应该更为复杂,暂不管// while (true) {// Node first = dummy.next.get();// if (first == null) {// try {// Thread.sleep(Double.valueOf(Math.random() * 1000).longValue());// continue;// } catch (InterruptedException ex) {// Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex);// }// }// Node second = first.next.get();// if(){//// }// if (dummy.next.compareAndSet(first, second)) {// return first;// }// } return null; } public static void main(String args[]) { TestConcurrentQueue queue = new TestConcurrentQueue(); CyclicBarrier barrier = new CyclicBarrier(1000);//保证线程同一时间起跑 List<Thread> list = new ArrayList(); for (int i = 0; i < 510; i++) { Thread t = new Thread(new pusher(queue, barrier)); list.add(t); t.start(); } for (int i = 0; i < 490; i++) { Thread t = new Thread(new poper(queue, barrier)); list.add(t); t.start(); } for (Thread t : list) { try { t.join(); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } System.out.println("-------以下将打印出当前堆栈中的各个对象-----"); Node curNode = queue.dummy.next.get(); int i = 0; while (curNode != null) { System.out.println("【" + curNode.value + "】"); curNode = curNode.next.get(); i++; } System.out.println("------------------栈中还有【" + i + "】个数据----------------------"); } public static class pusher implements Runnable { TestConcurrentQueue stack; CyclicBarrier barrier; public pusher(TestConcurrentQueue stack, CyclicBarrier barrier) { this.stack = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); this.stack.push(Thread.currentThread().getName() + "插入数据"); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } } public static class poper implements Runnable { TestConcurrentQueue queue; CyclicBarrier barrier; public poper(TestConcurrentQueue stack, CyclicBarrier barrier) { this.queue = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); Object value = this.queue.pop(); if (value != null) { System.out.println(Thread.currentThread().getName() + "删除了数据【" + value + "】"); } else {// System.out.println(Thread.currentThread().getName() + "当前栈顶为空 【 】 "); } } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStack.class.getName()).log(Level.SEVERE, null, ex); } } } /** * 代表节点 */ public static class Node { AtomicReference<Node> next = new AtomicReference<Node>(); public Object value; public Node() { } public Node(AtomicReference<Node> next, Object value) { this.next = next; this.value = value; } @Override public boolean equals(Object obj) { if (obj instanceof Node && value != null) { return value.equals(((Node) obj).value); } return false; } }}
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */package TestConcurrent;import java.util.ArrayList;import java.util.List;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;import java.util.logging.Level;import java.util.logging.Logger;/** * 尝试使用AtomicReferenceFieldUpdater的compareAndSet实现同步的堆栈 * 注意一点CAS对比锁的使用,在中低级的竞争环境下可以提供更高的效率 * AtomicReferenceFieldUpdater可以以CompareAndSet的方式更新【volatil】变量 */public class TestConcurrentStackFiledUpdater {//使用AtomicReference、构建Node类型的原子变量,代表当前栈顶 volatile Node top = new Node(); private static final AtomicReferenceFieldUpdater<TestConcurrentStackFiledUpdater, Node> topUpdater = AtomicReferenceFieldUpdater.newUpdater(TestConcurrentStackFiledUpdater.class, Node.class, "top"); /** * newUpdater public static <U,W> AtomicReferenceFieldUpdater<U,W> * newUpdater(Class<U> tclass, Class<W> vclass, String * fieldName)使用给定的字段为对象创建和返回一个更新器。需要 Class 参数检查反射类型和一般类型是否匹配。 * 参数: tclass - * 保持字段的对象类。 vclass - 该字段的类 fieldName - 要更新的字段名称。 */ public TestConcurrentStackFiledUpdater() { } public void push(Object value) { //获得当前top值以使用cas Node oldHead; Node newHead; do { oldHead = topUpdater.get(this); newHead = new Node(oldHead, value); } while (!topUpdater.compareAndSet(this, oldHead, newHead)); } public Object pop() { Node oldHead; Node newHead = null; Boolean result = false; do { oldHead = topUpdater.get(this); if (oldHead == null || oldHead.next == null) { try { Thread.sleep(Double.valueOf(Math.random() * 1000).longValue()); continue; } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } } newHead = oldHead.next; result = topUpdater.compareAndSet(this, oldHead, newHead); } while (!result); return oldHead.value; } public static void main(String args[]) { TestConcurrentStackFiledUpdater stack = new TestConcurrentStackFiledUpdater(); CyclicBarrier barrier = new CyclicBarrier(1000);//保证线程同一时间起跑 List<Thread> list = new ArrayList(); for (int i = 0; i < 510; i++) { Thread t = new Thread(new pusher(stack, barrier)); list.add(t); t.start(); } for (int i = 0; i < 490; i++) { Thread t = new Thread(new poper(stack, barrier)); list.add(t); t.start(); } for (Thread t : list) { try { t.join(); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } } System.out.println("-------以下将打印出当前堆栈中的各个对象-----"); Node curNode = stack.topUpdater.get(stack); int i = 0; while (curNode != null) { System.out.println("【" + curNode.value + "】"); curNode = curNode.next; i++; } System.out.println("------------------栈中还有【" + i + "】个数据----------------------"); } public static class pusher implements Runnable { TestConcurrentStackFiledUpdater stack; CyclicBarrier barrier; public pusher(TestConcurrentStackFiledUpdater stack, CyclicBarrier barrier) { this.stack = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); this.stack.push(Thread.currentThread().getName() + "插入数据"); } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } } } public static class poper implements Runnable { TestConcurrentStackFiledUpdater stack; CyclicBarrier barrier; public poper(TestConcurrentStackFiledUpdater stack, CyclicBarrier barrier) { this.stack = stack; this.barrier = barrier; } @Override public void run() { try { barrier.await(); Thread.sleep(1000); Object value = this.stack.pop(); if (value != null) { System.out.println(Thread.currentThread().getName() + "删除了数据【" + value + "】"); } else {// System.out.println(Thread.currentThread().getName() + "当前栈顶为空 【 】 "); } } catch (InterruptedException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } catch (BrokenBarrierException ex) { Logger.getLogger(TestConcurrentStackFiledUpdater.class.getName()).log(Level.SEVERE, null, ex); } } } /** * 代表节点 */ public static class Node { public Node next; public Object value; public Node() { } public Node(Node next, Object value) { this.next = next; this.value = value; } @Override public boolean equals(Object obj) { if (obj instanceof Node && value != null) { return value.equals(((Node) obj).value); } return false; } }}
0 0
- 笔记_并发编程实践_十五
- 笔记_并发编程实践_十一
- 笔记_并发编程实践_十二
- 笔记_并发编程实践_十三
- 笔记_并发编程实践_十四
- 笔记_并发编程实践_十六
- 并发编程实践笔记_第五章
- 多线程并发实践_笔记_第六章
- 多线程并发实践_笔记_第七章
- 多线程并发实践_笔记_第八章
- 多线程并发实践_笔记_第九章
- 多线程并发实践_笔记_第十章
- 黑马程序员_并发编程笔记_初学简单概念
- Java并发编程实战笔记_并发任务执行
- Java并发编程实战笔记_并发任务执行
- 代码整洁_并发编程
- 并发编程实践 -- 笔记
- 并发_同步_异步_事件驱动编程
- 黑马程序员_泛型总结(2)
- 全局变量和局部变量在内存里的区别
- 杭电1061 解题报告
- 黑马程序员------------------网络编程
- BST 前序,中序,后序遍历,Iterative Method
- 笔记_并发编程实践_十五
- 哥哥 我们去哪儿
- 我们能从java的HelloWorld学到什么?
- 强大的list列表解析功能
- 黑马程序员_动态代理
- 未分类--Windows API--Int32x32To64
- GCC4.4.3安装【light测试成功】
- 代理类,有带验证的代理及不待验证的代理,也可以选择直连不使用代理
- 黑马程序员------------------正则表达式