版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
AtomicBoolean 与 线程原子性
参考:
AtomicBoolean 的api简单使用:
public class Test2 {
@Test
public void test1() {
AtomicBoolean exists = new AtomicBoolean(false);
System.out.println("get================" +
exists.get());//false
}
/**
* compareAndSet(boolean expect, boolean update)
* boolean expect: 期望的值,
* boolean update: 替换的值
* return: 如果expect等于当前值返回true,否则返回false
* 先对比compare,再替换set
*/
@Test
public void test2() {
AtomicBoolean exists = new AtomicBoolean(false);
System.out.println("get1================" +
exists.get());//false
System.out.println("compareAndSet1====" +
exists.compareAndSet(false, true));//true
System.out.println("get2================" +
exists.get());//true
}
@Test
public void test3() {
AtomicBoolean exists = new AtomicBoolean(false);
System.out.println("get1================" +
exists.get());//false
System.out.println("compareAndSet2====" +
exists.compareAndSet(true, false));//false
System.out.println("get2================" +
exists.get());//false
}
@Test
public void test4() {
AtomicBoolean exists = new AtomicBoolean(false);
exists.set(true);
System.out.println("get===========" +
exists.get());//true
}
/**
* getAndSet(boolean newValue):
* boolean newValue : 设置新的值
* 先get旧值返回,再set新值
*/
@Test
public void test5() {
AtomicBoolean exists = new AtomicBoolean(false);
boolean get = exists.getAndSet(true);
System.out.println("get1===========" + get);//false
System.out.println("get2===========" + exists.get());//true
}
}
AtomicBoolean原子性测试
AtomicBoolean具有原子性,在多线程的环境下使用是线程安全的;
举个例子,在多线程环境中,我们通过判断一个boolan变量的值,然后修改该变量的值,之后进行操作;
存在一个问题就是,多个线程可能都读到该变量的值是符合条件的,然后都去修改了变量的值;
其实只需要一个线程执行就可以了,主要的原因就是因为if判断和set值是两个操作,这里面存在线程安全的问题;
Atomic类型的变量就不存在这种问题;
下面通过一个例子来说明;
public class TestActivity extends AppCompatActivity {
private boolean aBoolean = false;
private AtomicBoolean atomicBoolean = new AtomicBoolean();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyRunnable runnable1 = new MyRunnable("runnable1");
MyRunnable runnable2 = new MyRunnable("runnable2");
new Thread(runnable1).start();
new Thread(runnable2).start();
AtomaticRunnable atomaticRunnable1 =
new AtomaticRunnable("atomaticRunnable1");
AtomaticRunnable atomaticRunnable2 =
new AtomaticRunnable("atomaticRunnable2");
new Thread(atomaticRunnable1).start();
new Thread(atomaticRunnable2).start();
}
public class MyRunnable implements Runnable {
private String mName;
public MyRunnable(String name) {
mName = name;
}
@Override
public void run() {
if (!aBoolean) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
aBoolean = true;
System.out.println(mName +
"============enter");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(mName +
"============leave");
aBoolean = false;
} else {
System.out.println(mName +
"===========give up");
}
}
}
//runnable1============enter
//runnable2============enter
//runnable1============leave
//runnable2============leave
public class AtomaticRunnable implements Runnable {
private String mName;
public AtomaticRunnable(String name) {
mName = name;
}
@Override
public void run() {
if (atomicBoolean.compareAndSet(false, true)) {
System.out.println("=========" +
mName + "==========enter");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========" +
mName + "==========leave");
atomicBoolean.set(false);
} else {
System.out.println("=========" +
mName + "==========give up");
}
}
}
//=========atomaticRunnable1==========enter
//=========atomaticRunnable2==========give up
//=========atomaticRunnable1==========leave
}
可见AtomicBoolean只执行了一个线程;
这里使用了compareAndSet。
这个方法主要两个作用
-
比较AtomicBoolean和expect的值,如果一致,执行方法内的语句。其实就是一个if语句
-
把AtomicBoolean的值设成update,
比较最要的是这两件事是一气呵成的,这连个动作之间不会被打断,任何内部或者外部的语句都不可能在两个动作之间运行。