精华内容
下载资源
问答
  • [超级链接:Java并发学习系列-绪论] 在Java并发编程中,如果要保证代码的安全性,则必须保证代码的原子性、可见性和有序性。 在 Java并发12:并发三特性-...原子定义:一个或多个操作,要么全部执行且在执行过...

    [超级链接:Java并发学习系列-绪论]

    在Java并发编程中,如果要保证代码的安全性,则必须保证代码的原子性、可见性和有序性。

    Java并发12:并发三特性-原子性、可见性和有序性概述及问题示例中,对并发中的三个特性(原子性、可见性和有序性)进行了初步学习。

    本章主要就Java中保障原子性的技术进行更加全面的学习。

    1.整体回顾

    • 原子性定义:一个或多个操作,要么全部执行且在执行过程中不被任何因素打断,要么全部不执行。
    • Java自带原子性:对基本数据类型的变量读取赋值操作是原子性操作。

    2.原子性问题

    由上面的章节已知,不采取任何的原子性保障措施的自增操作并不是原子性的。
    下面的代码实现了一个自增器(不是原子性的)。

    /**
     * <p>原子性示例:不是原子性</p>
     *
     * @author hanchao 2018/3/10 14:58
     **/
    static class Increment {
        private int count = 1;
    
        public void increment() {
            count++;
        }
    
        public int getCount() {
            return count;
        }
    }

    下面的代码展示了在多线程环境中,调用此自增器进行自增操作。

    int type = 0;//类型
    int num = 50000;//自增次数
    int sleepTime = 5000;//等待计算时间
    int begin;//开始的值
    Increment increment;
    //不进行原子性保护的大范围操作
    increment = new Increment();
    begin = increment.getCount();
    LOGGER.info("Java中普通的自增操作不是原子性操作。");
    LOGGER.info("当前运行类:" +increment.getClass().getSimpleName() +  ",count的初始值是:" + increment.getCount());
    for (int i = 0; i < num; i++) {
        new Thread(() -> {
            increment.increment();
        }).start();
    }
    //等待足够长的时间,以便所有的线程都能够运行完
    Thread.sleep(sleepTime);
    LOGGER.info("进过" + num + "次自增,count应该 = " + (begin + num) + ",实际count = " + increment.getCount());

    某次运行结果:

    2018-03-17 22:52:23 INFO  ConcurrentAtomicityDemo:132 - Java中普通的自增操作不是原子性操作。
    2018-03-17 22:52:23 INFO  ConcurrentAtomicityDemo:133 - 当前运行类:Increment,count的初始值是:1
    2018-03-17 22:52:33 INFO  ConcurrentAtomicityDemo:141 - 进过50000次自增,count应该 = 50001,实际count = 49999

    通过观察结果,发现程序确实存在原子性问题。

    3.原子性技术保障

    在Java中提供了多种原子性保障措施,这里主要涉及三种:

    • 通过synchronized关键字定义同步代码块或者同步方法保障原子性。
    • 通过Lock接口保障原子性。
    • 通过Atomic类型保障原子性。

    3.1.synchronized关键字

    Increment类进行扩展:

    /**
     * <p>原子性示例:通过synchronized保证代码块的原子性</p>
     *
     * @author hanchao 2018/3/10 15:07
     **/
    static class SynchronizedIncrement extends Increment {
        /**
         * <p>添加关键字synchronized,使之成为同步方法</p>
         *
         * @author hanchao 2018/3/10 15:12
         **/
        @Override
        public synchronized void increment() {
            super.count++;
        }
    }

    在多线程环境中进行SynchronizedIncrement 的自增:

    //synchronized关键字能够保证原子性(代码块锁,多线程操作某一对象时,在某个代码块内只能单线程执行)
    increment = new SynchronizedIncrement();
    begin = increment.getCount();
    LOGGER.info("可以通过synchronized关键字保障代码的原子性");
    LOGGER.info("当前运行类:" +increment.getClass().getSimpleName() +  ",count的初始值是:" + increment.getCount());
    for (int i = 0; i < num; i++) {
        new Thread(() -> {
            increment.increment();
        }).start();
    }
    //等待足够长的时间,以便所有的线程都能够运行完
    Thread.sleep(sleepTime);
    LOGGER.info("进过" + num + "次自增,count应该 = " + (begin + num) + ",实际count = " + increment.getCount());

    运行结果(多次):

    2018-03-18 00:41:30 INFO  ConcurrentAtomicityDemo:147 - 可以通过synchronized关键字保障代码的原子性
    2018-03-18 00:41:30 INFO  ConcurrentAtomicityDemo:148 - 当前运行类:SynchronizedIncrement,count的初始值是:1
    2018-03-18 00:41:40 INFO  ConcurrentAtomicityDemo:156 - 进过50000次自增,count应该 = 50001,实际count = 50001

    通过多次运行,发现运行结果一致,所以可以确定synchronized关键字能够保证代码的原子性

    3.2.Lock接口

    Increment类进行扩展:

    /**
    * <p>原子性示例:通过Lock接口保证指定范围代码的原子性</p>
    *
    * @author hanchao 2018/3/10 15:14
    **/
    static class LockIncrement extends Increment {
       //定义个读写锁:锁内运行多线程读,单线程写
       private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    
       /**
        * <p>运用读写所重写方法</p>
        *
        * @author hanchao 2018/3/10 15:13
        **/
       @Override
       public void increment() {
           //写锁 加锁
           readWriteLock.writeLock().lock();
           try {
               //开始写
               super.count++;
           } finally {
               //将解锁放在finally块中,保证必然执行,防止死锁
               readWriteLock.writeLock().unlock();
           }
       }
    }

    在多线程环境中进行LockIncrement的测试:

    //通过Lock接口保证原子性操作
    increment = new LockIncrement();
    begin = increment.getCount();
    LOGGER.info("可以通过Lock接口保证代码的原子性");
    LOGGER.info("当前运行类:" +increment.getClass().getSimpleName() +  ",count的初始值是:" + increment.getCount());
    for (int i = 0; i < num; i++) {
        new Thread(() -> {
            increment.increment();
        }).start();
    }
    //等待足够长的时间,以便所有的线程都能够运行完
    Thread.sleep(sleepTime);
    LOGGER.info("进过" + num + "次自增,count应该 = " + (begin + num) + ",实际count = " + increment.getCount());

    运行结果(多次):

    2018-03-18 10:12:12 INFO  ConcurrentAtomicityDemo:163 - 可以通过Lock接口保证代码的原子性
    2018-03-18 10:12:12 INFO  ConcurrentAtomicityDemo:164 - 当前运行类:LockIncrement,count的初始值是:1
    2018-03-18 10:12:29 INFO  ConcurrentAtomicityDemo:172 - 进过50000次自增,count应该 = 50001,实际count = 50001

    通过多次运行,发现运行结果一致,所以可以确定Lock接口能够保证代码的原子性

    3.3.Atomic类型

    Increment类进行扩展:

    /**
    * <p>原子性示例:通过Atomic类型保证类型的原子性</p>
    *
    * @author hanchao 2018/3/10 15:19
    **/
    static class AtomicIncrement {
       private AtomicInteger count = new AtomicInteger(1);
    
       /**
        * <p>无需其他处理,直接自增即可</p>
        *
        * @author hanchao 2018/3/10 15:21
        **/
       public void increment() {
           count.getAndIncrement();
       }
    
       public AtomicInteger getCount() {
           return count;
       }
    }

    在多线程环境中进行AtomicIncrement的测试:

    //通过Atomic变量保证变量操作的原子性
    AtomicIncrement increment1 = new AtomicIncrement();
    begin = increment1.getCount().get();
    LOGGER.info("可以通过Atomic类型保证变量的原子性");
    LOGGER.info("当前运行类:" +increment1.getClass().getSimpleName() +  ",count的初始值是:" + increment1.getCount());
    for (int i = 0; i < num; i++) {
        new Thread(() -> {
            increment1.increment();
        }).start();
    }
    //等待足够长的时间,以便所有的线程都能够运行完
    Thread.sleep(sleepTime);
    LOGGER.info("进过" + num + "次自增,count应该 = " + (begin + num) + ",实际count = " + increment1.getCount());

    运行结果(多次):

    2018-03-18 10:14:37 INFO  ConcurrentAtomicityDemo:178 - 可以通过Atomic类型保证变量的原子性
    2018-03-18 10:14:37 INFO  ConcurrentAtomicityDemo:179 - 当前运行类:AtomicIncrement,count的初始值是:1
    2018-03-18 10:14:48 INFO  ConcurrentAtomicityDemo:187 - 进过50000次自增,count应该 = 50001,实际count = 50001

    通过多次运行,发现运行结果一致,所以可以确定Atomic类型能够保证代码的原子性

    4.总结

    经验证,以下三种措施,可以保证Java代码在运行时的原子性:

    • synchronized关键字
    • Lock接口
    • Atomic类型

    并发三特性总结

    特性 volatile关键字 synchronized关键字 Lock接口 Atomic变量
    原子性 无法保障 可以保障 可以保障 可以保障
    可见性 可以保障 可以保障 可以保障 可以保障
    有序性 一定程度保障 可以保障 可以保障 无法保障
    展开全文
  • [超级链接:Java并发学习系列-绪论] 在Java并发编程中,如果要保证代码的安全性,则必须保证代码的原子性、可见性和有序性。 在 Java并发12:并发三特性-...有序定义:即程序执行的顺序按照代码的先后顺序执行...

    [超级链接:Java并发学习系列-绪论]

    在Java并发编程中,如果要保证代码的安全性,则必须保证代码的原子性、可见性和有序性。

    Java并发12:并发三特性-原子性、可见性和有序性概述及问题示例中,对并发中的三个特性(原子性、可见性和有序性)进行了初步学习。
    本章主要就Java中保障有序性的技术进行更加全面的学习。

    1.整体回顾

    • 有序性定义:即程序执行的顺序按照代码的先后顺序执行。
    • Java自带有序性:happens-before原则。

    2.有序性问题

    其他大牛们经常拿下面的代码作为有序性的示例:

    //线程1:
    context = loadContext();   //语句1
    inited = true;             //语句2
    
    //线程2:
    while(!inited ){
      sleep()
    }
    doSomethingwithconfig(context);

    不过本人并没有通过实际编程运行,来证明此段程序的无序性。


    为了更形象的理解有序性问题,本人使用了后面的示例,虽然后面的示例对有序性体现不够准确。

    如果各位看官,有更好的能够实际体现有序性问题的示例,请一定告知,十分感谢!

    场景说明:

    • 有两个线程A和线程B。
    • 线程A对变量x进行加法和减法操作。
    • 线程B对变量x进行乘法和出发操作。

    代码:
    这里的示例只是为了方便得到无序的结果而专门写到,所以有些奇特。

    static String a1 = new String("A : x = x + 1");
    static String a2 = new String("A : x = x - 1");
    static String b1 = new String("B : x = x * 2");
    static String b2 = new String("B : x = x / 2");
    
    //不采取有序性措施,也没有发生有序性问题.....
    LOGGER.info("不采取措施:单线程串行,视为有序;多线程交叉串行,视为无序。");
    new Thread(() -> {
        System.out.println(a1);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(a2);
    }).start();
    new Thread(() -> {
        System.out.println(b1);
        System.out.println(b2);
    }).start();

    运行结果:

    2018-03-18 00:16:20 INFO  ConcurrentOrderlyDemo:63 - 不采取措施:单线程串行,视为有序;多线程交叉串行,视为无序。
    A : x = x + 1
    B : x = x * 2
    B : x = x / 2
    A : x = x - 1

    通过运行结果发现,多线程环境中,代码是交替的串行执行的,这样会导致产生意料之外的结果。

    3.有序性技术保障

    在Java中提供了多种有序性保障措施,这里主要涉及两种:

    • 通过synchronized关键字定义同步代码块或者同步方法保障有序性。
    • 通过Lock接口保障有序性。

    3.1.synchronized关键字

    定义一个对象用于同步块:

    //定义一个对象用于同步块
    static byte[] obj = new byte[0];

    在多线程环境中进行synchronized关键字的有序性测试:

    LOGGER.info("通过synchronized保证有序性:成功");
    //通过synchronized保证有序性
    new Thread(() -> {
        synchronized (obj) {
            System.out.println(a1);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(a2);
        }
    }).start();
    new Thread(() -> {
        synchronized (obj) {
            System.out.println(b1);
            System.out.println(b2);
        }
    }).start();

    运行结果(多次):

    2018-03-18 11:02:25 INFO  ConcurrentOrderlyDemo:79 - 通过synchronized保证有序性:成功
    A : x = x + 1
    A : x = x - 1
    B : x = x * 2
    B : x = x / 2

    通过多次运行,发现运行结果一致,所以可以确定synchronized关键字能够保证代码的有序性

    3.2.Lock接口

    定义一个Lock锁:

    //定义一个Lock锁
    static ReentrantLock reentrantLock = new ReentrantLock(true);

    在多线程环境中进行Lock接口的有序性测试:

    LOGGER.info("通过Lock保证有序性:成功");
    //通过Lock保证有序性
    new Thread(() -> {
        reentrantLock.lock();
        System.out.println(a1);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(a2);
        reentrantLock.unlock();
    }).start();
    new Thread(() -> {
        reentrantLock.lock();
        System.out.println(b1);
        System.out.println(b2);
        reentrantLock.unlock();
    }).start();

    运行结果(多次):

    2018-03-18 11:03:34 INFO  ConcurrentOrderlyDemo:100 - 通过Lock保证有序性:成功
    A : x = x + 1
    A : x = x - 1
    B : x = x * 2
    B : x = x / 2

    通过多次运行,发现运行结果一致,所以可以确定Lock接口能够保证代码的有序性

    4.总结

    经验证,以下两种措施,可以保证Java代码在运行时的有序性:

    • synchronized关键字
    • Lock接口

    并发三特性总结

    特性 volatile关键字 synchronized关键字 Lock接口 Atomic变量
    原子性 无法保障 可以保障 可以保障 可以保障
    可见性 可以保障 可以保障 可以保障 可以保障
    有序性 一定程度保障 可以保障 可以保障 无法保障
    展开全文
  • 一、原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着...那么java内存模型中定义了8种原子方法,这8中方法也不能再拆分 1.lock(锁定)用于锁定主内存中变量,将他变成一个线程独占的状...

    一、原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。

    像是a++  并不是原子操作,因为a++其实包括,读取a的值,将a的值加1,将结果赋值给a

    那么java内存模型中定义了8种原子方法,这8中方法也不能再拆分

     1.lock(锁定)用于锁定主内存中变量,将他变成一个线程独占的状态

     2.unlock(解锁)用于解锁变量被单线程独占的状态

     3.read(读取),用于主内存中的变量,读取到工作内存中,以便load动作使用

     4.load(加载),将read读取的内容放入变量副本中。

     5.use(使用),将工作内存中的变量值,传递给执行引擎,

     6.assign(赋值) 把从执行引擎传来的值,赋值给工作变量

     7.store(存储) 将工作内存中的变量,传递给主存,以便于后面wirte的使用

     8.write(写) 将它把store操作从工作内存中得到的变量的值放入主内存的变量中

    注意:java内存模型只是保证他们每个操作是原子性的

    由原子性变量操作read,load,use,assign,store,write,可以大致认为基本数据类型的访问读写具备原子性(例外就是long和double的非原子性协定)

     

    将一个变量从主内存中放到线程内存中,需要使用read和load操作,线程内存中的值放入主内存中,需要使用store和write操作

    其中六条可以满足基本数据类型的访问读写具备原子性,还剩下lock和unlock两条原子操作。如果我们需要更大范围的原子性操作就可以使用lock和unlock原子操作。尽管jvm没有把lock和unlock开放给我们使用,但jvm以更高层次的指令monitorenter和monitorexit指令开放给我们使用,反应到java代码中就是---synchronized关键字,也就是说synchronized满足原子性

    二、有序性

      在单例模式的实现上有一种双重检验锁定的方式(Double-checked Locking),我们知道在创建对象时,其实是三步操作

                    instance = new Singleton();

     1.为对象份分配内存空间,2.创建对象,3.对象指向内存空间

    那么我们的jmm在满足happend-before规则的情况下,允许处理器进行指令重排序,也就是说在不影响结果的情况下,可以进行指令重排序, 1 2 步执行的先后顺序,对结果没有影响,因此可以发生指令重排序,当AB 线程方式访问时,可能A在执行了

       instance = new Singleton(); 操作后,释放了锁,释放锁以后,先执行的如果是创建对象,那么B在获得锁以后,也会导致判断不为null的情况。

    三、可见性

     

    可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。通过之前对synchronzed内存语义进行了分析,当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,synchronized具有可见性。同样的在volatile分析中,会通过在指令中添加lock指令,以实现内存可见性。因此, volatile具有可见性

     

     

    展开全文
  • volatile的可见性、原子性、有序性? 1.什么是volatile? volatile是Java虚拟机提供的轻量级的同步机制 2.volatile特性 可见性 不保证原子性 禁止指令重排(有序性) 3.具体介绍 ​ 具体介绍之前,介绍一个概念...

    volatile的可见性、原子性、有序性?

    1.什么是volatile?

    volatile是Java虚拟机提供的轻量级的同步机制

    2.volatile特性

    • 可见性
    • 不保证原子性
    • 禁止指令重排(有序性)

    3.具体介绍

    ​ 具体介绍之前,介绍一个概念JMM(Java内存模型Java Memory Model,简称JMM)本身是一种抽象的概念,并不真实存在,它描述一组规范或规则,通过此规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问模式。

    JMM关于同步的规定:

    			1. 线程解锁前,必须把共享变量的值刷新回主内存
    			2. 线程加锁前,必须读取主内存的最新值到自己的工作内存
    			3. 加锁解锁是同一把锁
    

    出现了几个新名词:

    主内存

    工作内存

    共享变量

    ​ 由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(栈空间),工作内存是每个现成的私有数据区,而java内存模型中规定所有变量都存储再主内存,主内存是共享内存区,所有线程可以访问,但线程对变量的操作(读取赋值等)必须在工作内存进行,首先将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量。不同线程无法访问对方的工作内存,线程间的传值必须通过主内存来完成。

    ​ 这里的描述可以看出主内存就像JVM模型中的方法区。而工作内存就像操作数栈
    在这里插入图片描述

    3.1可见性

    ​ 可见性就是线程对变量操作后写回主内存,其他线程可以看到更新后的值。

    代码演示

    package JVM;
    
    class MyData {
    
        volatile int num = 0;
    
        public void To60() {
            this.num = 60;
        }
    }
    
    /**
     * 验证volatile可见性
     **/
    public class VolatileDemo {
        public static void main(String[] args) {
    
            MyData myData = new MyData();
    
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t come in");
    
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myData.To60();
    
                System.out.println(Thread.currentThread().getName() + "\t update num value: " + myData.num);
            }, "t1").start();
    
            //第二个线程是main
            while (myData.num == 0) {
                
            }
    
            System.out.println(Thread.currentThread().getName() + "\t misson is over: " + myData.num);
        }
    }
    
    

    结果
    在这里插入图片描述

    若num属性不加volatile,main线程拿到的num值是0不可见更新后的值,结果将是一直在循环中!

    3.2 原子性

    原子性就是说一个操作不可以被中途cpu暂停然后调度,即不能被中断。 要不就执行完,要不就不执行。 如果一个操作是原子性的,那么在多线程环境下,就不会出现变量被修改等奇怪的问题。

    代码演示

    package JVM;
    
    class MyData {
    
        volatile int num = 0;
    
        public void To60() {
            this.num = 60;
        }
    
        public void add() {
            this.num++;
        }
    }
    
    
    public class VolatileDemo {
        public static void main(String[] args) {
    
            MyData myData = new MyData();
    
            for (int i = 1; i <= 20; i++) {//创建20个线程
                new Thread(() -> {
                    for (int j = 1; j <= 1000; j++) {//每个线程1000次+1操作
                        myData.add();
                    }
                }, String.valueOf(i)).start();
            }
    
            //默认main线程和GC线程,其余是我们创建的
            while (Thread.activeCount() > 2) {
                Thread.yield();
            }
    
            //非默认线程执行完后
            System.out.println("misson is over num = " + myData.num);
        }
        
    }
    
    

    结果
    在这里插入图片描述

    那么为什么结果不是20000?

    num++在多线程环境下是不安全的,原因是由于执行中某种问题(拿值太快、线程挂起)后面线程拿到的值不是前一个线程更新后的值,第一个线程由1边为2,第二个线程拿到的也是1更新后也是2,传回主内存原本应该是1+1+1=3,结果是第二个线程的2覆盖了第一个线程的2。


    为什么num++多线程不安全?

    原因如图
    在这里插入图片描述
    一个num++操作java来写是一句,但执行时候汇编成字节码是4句:从主内存取到工作内存、压栈、加操作、放回主内存。


    如何解决不保证原子性的问题?

    1. synchronized修饰add()

    2. 用java.util.concurrent下的AtomicInteger

    在这里插入图片描述在这里插入图片描述

    3.3禁止指令重排

    指令重排是多线程中编译成字节码,优化执行顺序进行的操作

    代码示例:

    public void sort(){
        int x = 11;//语句1
        int y = 20;//语句2
        x = x +5;//语句3
        y = x*x;//语句4
    }
    

    正常执行顺序1234,指令重排后有可能就是1324。当然重排后语句4不可能排到第一位,因为有依赖关系(简单来说就是先有你爸后有你)

    对于特殊情况重排后结果可能不同如下例

    int a,b,x,y=0;
    
    //线程1
    x=a;
    b=1;
    //线程2
    y=b;
    a=2;
    
    
    //...执行结果
    //x=0 y=0
    

    如果编译器对这段代码重排优化后,可能出现下面情况

    //线程1
    b=1;
    x=a;
    //线程2
    a=2;
    y=b;
    
    //...执行结果
    //x=2 y=1
    

    综上所述volatile修饰保证可见性,禁止指令重排。

    4.什么时候用到volatile?

    单例模式双重锁检测用volatile禁止指令重排。
    详见: 单例模式和代理模式.中的双重锁检测

    展开全文
  • 原子性、可见性、有序性、 (1)原子原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败 ```javascript Int a = 10; //原子性 a++; //1.读取a的值 2.对a+1 3.更新的值赋给a Int b = a; //...
  • 定义:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 举个最简单的例子,大家想一下假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果? int i...
  • 在并发编程中,所有问题的根源就是可见性、原子性和有序性问题,这篇文章我们就来聊聊原子性问题。在介绍原子性问题之前,先来说下线程安全:线程安全我理解的线程安全就是不管单线程还是多线程并发的时候,始终能...
  • [超级链接:Java并发学习系列-绪论] 本章主要学习Java并发中的三个特性:原子性、可见性和有序性。 在Java并发编程中,如果要保证代码的安全性,则必须保证...1.1.原子定义 原子性:一个或多个操作,要么全部...
  • Java的原子性&&可见性&&有序

    千次阅读 2017-06-21 10:16:53
    Java的原子性&&可见性&&有序原子定义原子性:是指一个操作或多个操作要么全部执行,且执行的过程不会被任何因素打断,要么就都不执行。原子操作原理(处理器是如何实现原子操作的)处理器实现原子操作有3种...
  • 目录定义原子性AtomicXxxAtomicStampedReference可见性有序性参考资料 定义 首先大家需要思考一下何为线程安全性呢??? 《Java并发编程实战》书中给出定义:当多个线程访问某个类时,不管运行时环境采用何种调度...
  • 原子性,有序性和可见性 原子原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。 int a = 10; //1 a++; //2 int b=...
  • 线程安全性主要体现在三个方面:原子性、可见性、有序性。1.原子性(Atomicity)原子性是指一个原子操作在cpu中不可以暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行。原子操作保证...
  • 定义 描述 原子性 提供了互斥访问,同一时刻只能有一个线程对它进行操作 Java虚拟机对基本数据类的访问、读写都是具备原子性的(除long、double)--注意:i++操作是线程非安全的,即使...
  • 本章主要学习Java并发中的三个特性:原子性、可见性和有序性。 在Java并发编程中,如果要保证代码的安全...1.1.原子定义 原子性:一个或多个操作,要么全部执行且在执行过程中不被任何因素打断,要么全部不执行。...
  • 1.定义 原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 2.实例 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么必然包括2个操作:...
  • 三大性质总结:原子性、可见性以及有序性 一. 原子原子性指的是一个操作是不可中断的,要么全部执行成功要么全部执行失败。 int a = 10; //1 a++; //2 int b = a; //3 a = a + 1; //4 以上四句代码中,...
  • 目录Java内存模型原子性可见性有序性Happen Before 规则 Java内存模型 ​ Java虚拟机规范试图定义一种Java内存模型(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让Java程序在各种平台上都能达到一致的内存...
  • 作者:溪~源blog.csdn.net/xuan_lu/article/details/114451886目录定义原子性AtomicXxxAtomicStampedReference可见性...
  • 1.引入 众所周知,现在计算机多数还都是基于冯诺依曼计算机模型,这也是...它所定义的规范规定了程序中的变量在共享数据区域和私有数据区域的访问方式,主要是围绕原子性,有序性、可见性展开。 JMM把内存分为了主内存
  • java内存模型中定义了8中操作都是原子的,不可再分的。 lock(锁定):作用于主内存中的变量,它把一个变量标识为一个线程独占的状态; unlock(解锁):作用于主内存中的变量,它把一个处于锁定状态的变量释放出来,...
  • 一、定义:什么是线程安全性当多个线程访问某个类时,不管运行时环境采用 何种调度方式 或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类就是...
  • 有序性 在Java中提供了一系列和并发处理相关的关键字,比如volatile、Synchronized、final、juc等,这些就是Java内存 模型封装了底层的实现后提供给开发人员使用的关键字,在开发多线程代码的时候,我们可以直接...
  • 并发编程并发程序要正确地执行,必须要保证其具备原子性、可见性以及有序性;只要有一个没有被保证,就有可能会导致程序运行不正确线程不安全在编译、测试甚至上线使用时,并不一定能发现,因为受到当时的CPU调度...
  • 线程安全性详解(原子性、可见性、有序性)

    千次阅读 多人点赞 2019-10-22 10:00:52
    一、定义:什么是线程安全性 当多个线程访问某个类时,不管运行时环境采用 何种调度方式 或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类...
  • 由于并发程序比串行程序复杂得多,其中一...JMM的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的,下面我们来了解这些概念; JMM:JMM描述了Java程序中各种变量(线程共享变量)的访问规则,以及在J...
  • 内存模型与运行时数据区内存模型java内存模型简称JMM(Java Memory Model ),定义了程序中各个共享变量的访问规则。Java Memory Model变量...JMM规范定义了工作内存和主内存之间变量访问的细节,通过保障原子性、有序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 629
精华内容 251
关键字:

原子有序定义