java多线程-原子类AtomicBoolean
JDK1.5之后的java.util.concurrent.atomic包里多了一批原子处理类。AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。他们主要用于在高并发环境下的高效程序处理,来帮助我们简化同步处理。当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当A某个线程进入方法执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,
本篇要讲的主角是:AtomicBoolean,AtomicBoolean其实也就是一个boolean值,只是它是原子操作,是线程安全的。而我们常用的boolean是非线程安全的,非线程安全的操作在多线程操作时会给我们造成各种问题,所以在要求线程安全操作下的boolean类型的线程安全类AtomicBoolean就应运而生了,
在这个Boolean值的变化的时候不允许在它变化时插入其它指令 (通俗的话就是 AtomicBoolean 变量值改变之际不允许插入执行其它业务),保持操作的原子性
AtomicBoolean内compareAndSet(boolean expect, boolean update) 这个方法主的作用是:
比较AtomicBoolean当前值和expect的值,如果一致,则将update的值赋值给AtomicBoolean,并执行if判断内的业务。
且这两件事是一并执行的,是一气呵成的,这两个动作之间不会被打断,任何内部或者外部的语句都不可能在两个动作之间运行。为多线程的控制提供了解决的方案。
示例:需求是要实现同一时间只能是一个worker工作者在工作,当有worker在工作时,则其它 worker需要等待(进入堵塞状态),直至之前的worker完成工作,其它worker才可以进入工作
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class AtomicBooleanTest implements Runnable {
private static boolean isworking = false;
private String mWorkerName;
public AtomicBooleanTest(String name) {
this.mWorkerName = name;
}
@Override
public void run() {
normalTest();
//atomicTest();
//test();
}
public static void main(String[] args) {
AtomicBooleanTest worker1 = new AtomicBooleanTest("worker1");
AtomicBooleanTest worker2 = new AtomicBooleanTest("worker2");
new Thread(worker1).start();
new Thread(worker2).start();
}
private void normalTest() {
if (!isworking) {
System.out.println(mWorkerName + " enter"+" do somethings....");
isworking = true;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(mWorkerName + " ready to leave");
isworking = false;
} else {
System.out.println(mWorkerName + " other people is do somethings ,One moment please");
}
}
private static AtomicBoolean atomicWorking = new AtomicBoolean(false);
private void atomicTest() {
if(atomicWorking.compareAndSet(false, true)) {
System.out.println(mWorkerName + " enter"+" do somethings....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(mWorkerName + " ready to leave");
atomicWorking.set(false);
} else {
System.out.println(mWorkerName + " other people is do somethings ,One moment please");
}
}
private Boolean flag = false;
public void test() {
synchronized(flag) {
if(!flag) {
System.out.println("goin mWorkName = "+mWorkerName);
flag = true;
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("out mWorkName = "+mWorkerName);
flag = true;
}
}
}
}normalTest() 方法的执行结果: 很显然woker1 与worker2 并不没有按我们预期那样完成一个后而进入一个的方式处理业务,

atomicTest()方法的执行结果:当 worker1进入if内部后,worker2再尝试进入,结果是无法进入,
如下图,[1]标注处初始化赋值是false,当前执行到[2]标注处,此时会去判断标注[1]的值与标注[2]的值是否相等,
如果是相等,则将atomicWorking的值更新为标注[3]的值,并进入if内部执行业务,
如果不相等,则不能进入if内部,进入else内部

使用synchronized 公平锁的使用方式:此实现方式看其它博主的文章解释是无法达到线程安全的要求,但我测试了近20次都是可以,

源码:
public final void set(boolean newValue) { //设置新值
value = newValue ? 1 : 0;
}
/**
* Returns the current value,
* with memory effects as specified by {@link VarHandle#getVolatile}.
*
* @return the current value
*/
public final boolean get() { //返回当前值
return value != 0;
}
/**
* Atomically sets the value to {@code newValue} and returns the old value,
* with memory effects as specified by {@link VarHandle#getAndSet}.
*
* @param newValue the new value
* @return the previous value
*/
public final boolean getAndSet(boolean newValue) { //设置一个新值并返回旧值
return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
}getAndSet 方法示例







评论