原子性
是指在一次或者多次操作中,要么所有操作都执行成功,要么都执行不成功。
可见性
当一个线程对共享变量进行修改后,另外的线程可以立即看到修改后的值。
有序性
指代码在执行过程中的先后顺序,由于java编译器寄运行期的优化会导致执行顺序和代码顺序不一致。
Java内存模型(JMM)如何保证原子性,可见性,有序性
JMM只保证基本的读取和赋值的原子性操作其他都不保证,x=10是原子性的,x++,y=x之类的都是非原子性的。
java提供如下方式保证原子性:
使用synchronized关键字。
使用java.util.concurrent.atomic.*下的工具类保证原子性。
通过JUC提供的显式锁Lock。
java提供如下方式保证可见性:
使用volatile,当一个变量被volatile修饰时,对于变量的读写操作会直接在内存中进行(也会缓存到工作内存中,当一个线程对其进行修改后,其他线程工作内存中的该变量就会失效,所以必须从主内存中重新读取数据),先修改工作内存的变量值,然后立刻更新到主内存中。
使用synchronized,synchronized能保证同一时刻只有一个线程获得锁,然后执行同步方法,并且保证在释放锁之前将值更新到主内存。
通过JUC提供的显式锁Lock,Lock的lock方法保证同一时刻只有一个线程获得锁,然后执行同步方法,并且保证在释放锁之前将值更新到主内存。
java提供如下方式保证有序性:
使用volatile关键字。
使用synchronized关键字。
通过JUC提供的显式锁Lock。
volatile关键字

  1. volatile关键字只能修饰类变量和实例变量,对于方法参数、局部变量、以及实例常量、类常量都不能进行修饰。
  2. volatile不具备原子性。
  3. volatile具备可见性。
  4. volatile具备有序性。
    volatile关键字与synchronized的区别
    使用上的区别:
    1.volatile关键字只能修饰类变量和实例变量,对于方法参数、局部变量、以及实例常量、类常量都不能进行修饰。
    2.synchronized不能对变量行修改,只能修饰代码块和方法。
    3.volatile修饰变量可以为null,synchronized修饰的同步语句块monitor对象不能为null。
    对原子性的保证:
    1.volatile不具备原子性。
    2.synchronized的排他机制,所修饰的方法和代码块无法被中途打断,保证了原子性。
    对可见性的保证:
    1.synchronized借助于JVM的monitor enter 和monitor exit通过排他的方式使得代码串行化,在monitor exit时将共享资源都更新到主内存中。
    2.volatile使用机器指令的方式迫使其他线程中的共享变量失效,不得不到主内存中再次获取。
    对有序性的保证:
    1.volatile禁止JVM编译器以及处理器对其进行指令重排,保证有序性。
    2.synchronized的有序性是通过代码串行化换来的,所以代码块内的指令重排不会影响运行结果。
    其他:
    1.volatile不会使线程进入阻塞状态。
    2.synchronized会使线程进入阻塞状态。