zoukankan      html  css  js  c++  java
  • volatile不能保证原子性及其解决方案

    volatile不能保证原子性及其解决方案
    volatile类型的变量有三个特点
    1:可见性
    2:不能保证原子性
    3:禁止重排

    2、不能保证原子性
    或者说最终一致性不能得到保证,我们看如下案例

    import java.util.concurrent.TimeUnit;
    class MyData{//我们创建一个资源类
        volatile int number = 0;
        public void numberPlusPlus() {
            number++;
        }
    }
    public class VolatileDemo {    
        public static void main(String[] args) {
            MyData myData = new MyData();    
                for (int i = 1; i <=20; i++) {
                    new Thread(()->{//每次循环新建一个线程,一共创建20个线程
                        for (int j = 1; j <=1000; j++) {
                            myData.numberPlusPlus();
                  //每一个线程都使number自加1000次 } },String.valueOf(i)).start(); }
    try { TimeUnit.SECONDS.sleep(3);
              //设置3秒的时长 }
    catch (Exception e) { // TODO: handle exception } while (Thread.activeCount()>2) {
            //判断大于两个活跃线程,是因为,一个Java程序,还有主线程和gc线程 Thread.yield(); } System.out.println(Thread.currentThread().getName()
    +myData.number); } }



    很容易理解的一个程序,按照正常的想法来看20个线程,每个使number自加1000次
    应该的到20000的结果
    但是此程序实际运行结果则不然,基本运行的都不是20000(偶然情况下,也可以是,但是概率很小),这是因为多线程的情况下,各个线程抢占资源,对数据进行读写,有一部分是同时进行的看下图

    比如说 a线程此时拿到了number的值为0,b线程也拿到了number的值为0,他俩一起返回各自的内存工作区,进行自加操作,此时a线程中的number变为1,然后返回主内存中把主内存的number的值改写为1。b线程中的number在自己的内存工作区中,b线程把number自加为1,再去主内存中把number的值改写为1。
    此时很明显,number自加了两次,却最后的值为1
    这就是多线程中存在的一个问题,但是肯定万能的程序员肯定是有解决办法的
    这里给大家提供两种
    1:加锁synchronized(不推荐因为不是最优的办法)
    public ynchronized void numberPlusPlus() {
    number++;
    }
    2:AtomicInteger类型数据
    我的理解是原子integer类,这个类型的数据可以保证各个线程操作的是同一个数据,一个线程对该数据进行操作时,其他线程不能操作,这就保证的原子性或者说最终一致性
    AtomicInteger atomicInteger = new AtomicInteger();
    public void addAtomicInteger() {
    atomicInteger.getAndIncrement();
    //AtomicInteger类中有很多的方法
    //此时调用的方法表示自加
    //当然还有很多的方法,这就需要各位大牛自己研究了
    }

  • 相关阅读:
    第七章11
    第七章10
    第七章9
    第七章8
    第七章7
    第七章6
    第七章5
    第七章例7-13
    第七章例7-12
    第七章例7-11
  • 原文地址:https://www.cnblogs.com/liudongshuai/p/11728716.html
Copyright © 2011-2022 走看看