原子变量与非阻塞同步机制
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;
}
}
}