java : 并发线程: AtomicBoolean 与 线程原子性

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sinat_31057219/article/details/102729500

AtomicBoolean 与 线程原子性

参考:

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。

这个方法主要两个作用

  1. 比较AtomicBoolean和expect的值,如果一致,执行方法内的语句。其实就是一个if语句

  2. 把AtomicBoolean的值设成update,

比较最要的是这两件事是一气呵成的,这连个动作之间不会被打断,任何内部或者外部的语句都不可能在两个动作之间运行。

猜你喜欢

转载自blog.csdn.net/sinat_31057219/article/details/102729500