关键字-volatile
volatile是Java提供的一种轻量级的同步机制，Java中包含两种同步机制：
    |-同步方法、同步代码块 synchronized一般被称为重量级锁
    |-volatile变量，更轻量级，属于轻量级锁。因为它不会引起线程上下文的切换和调度。但是volatile变量的同步性比较差。也更容易出错。
作用：强制线程每次在使用的时候，都会看到共享区域的最新值

原子性：
    原子性其实是Java并发变成的多个概念之一，
    一次操作或多次操作中，要么所有的操作全部都得到了执行，并且不受到任何因素的干扰而中断。
    要么所有的操作都不执行，多个操作步骤是一个不能分割的整体。
    原子性就是拒绝多线程的，不论是单核还是多核，只要是具备原子性的量。同一时刻只能有一个线程对他进行操作。
    整个操作过程中，不会被线程调度器中断的操作，都可以认为是具有原子性的。
    比如：a=1，就是具有原子性的，a++或a+=1或a=a+1 他就不是原子性的操作。
    Java中的原子性操作：
        1、基本数据类型的读取和赋值操作，并且赋值必须是值给变量，变量之间的相互赋值就不属于原子性操作。
        2、Java中提供了一个包，整个包里面所有的类都属于原子性操作:java.util.concurrent.atomic
可见性：
    指的是当多个线程访问同一个变量的时候，一个线程改变了这个变量的值，其他线程能够立即看到修改的值。
    在多线程环境下啊，一个线程对共享变量进行了操作对于其他线程是不可见的，Java提供了volatile来保证共享变量的可见性。
    当一个变量被volatile修饰之后，表示线程的本地内存无效，当一个线程修改了共享变量之后它会立刻被更新到主内存中，
    其他的线程读取共享变量的时候，就可以直接到主内存读取。
    synchronized和Lock也可以保证共享变量的可见性。因为synchronized和Lock是保证同一时刻只有一个线程能够获取锁，
    并且执行同步代码，并且在释放锁之前会对变量的修改进行刷新，刷新到主内存中，所以才能保证可见性。

volatile：
    能够保证可见性，但是不能保证原子性。
    当我们定义了一个volatile修饰的变量后，虚拟机会把这个线程的本地内存中变量强制的刷新到主内存中。
    这个线程的写操作就会导致其他线程的volatile变量缓存无效。而是直接去主内存找变量。
volatile不能保证原子性。我们可以加锁，加锁之后，同一时间只能被一个线程执行，这种数据我们成为临界区数据，操作它的代码就称为临界区代码。
这样count++就成了原子操作。

原子性类：AtomicInteger
AtomicInteger是从JDK1.5开始提供的java.util.concurrent.atomic里一个类，这个包里面的原子操作类提供了一种方法：
可以比较高效的，简单的更新一个变量的方式。
atomic里面提供了13种类，属于4种类型的原子更新方式，分别是：
    原子更新基本数据类型
    原子更新数组
    原子更新引用
    原子更新属性
原子更新基本数据类型：
    AtomicInteger   原子更新整数类型
    AtomicBoolean   原子更新布尔类型
    AtomicLong      源自更新长整数类型
以AtomicInteger类型举例：
    构造方法：
        无参构造：new AtomicInteger()    初始化一个默认值(0)的原子类型Integer
        有参构造：new AtomicInteger(int v)   初始化一个指定参数的原子类型Integer
    普通方法：
        int get() 获取值
        int incrementAndGet() 以原子方式将当前的值+1，返回的是自增后的值
        int addAndGet(int delta)    以原子方式将参数添加到值。以原子的方式将输入的值和对象中值相加，得到最后的结果。
        int getAndSet(int value)     以原子方式设置为新的value值，并且把旧的值返回

AtomicInteger的内存分析以及基本原理
AtomicInteger原理是自旋锁+CAS算法

CAS算法全称是Compare And Swap 也就是 比较和交换。
算法公式 CAS(V,E,N)
    V：表示要更新的变量
    E：表示预期的值
    N：表示新值

如果V值等于E值，就把V的值设置为N，如果V值不等于E值，就说名已经有了其他线程完成了更新。
那么当前线程就什么都不做。就是CAS需要我们提供一个期望值，当期望值和当前线程的变量值相同，
说明还没有线程修改这个值，那么当前线程就可以进行修改，也就是执行CAS操作，如果期望值和
当前线程不符，说明这个值已经被其他线程修啊给i了，这个时候就不执行更新操作了，但是可以
重新选择读取这个变量，再次尝试修改这个变量，或者干脆放弃操作。

有3个操作数，内存的值V，表示要更新的变量。 旧的预期值E。要修改的值N
如果旧的预期值E==内存值V，表示修改成功，就是把V改为N
如果旧的预期值E!=内存值V，表示修改失败，不做任何操作。
并且重新获取现在的最新值，这个重新获取的动作就是【自旋】

乐观锁：CAS是从乐观状态的角度出发，它认为每次获取数据，别人都没有修改过，那么它就可以直接修改共享数据的值。
        CAS不会上锁，只会在修改共享数据之前，检查一些别人有没有修改这个数据。
悲观锁：synchronized是一个悲观锁的状态，总是从最坏的角度出发，认为每次获取数据的时候，别人都有可能修改了数据，所以每次操作共享数据之前，都会上锁。
CAS和synchronized相同点，都可以保证共享数据的安全性。
不同点：CAS是乐观锁，synchronized是悲观锁。



























