volatile关键字:若是一个变量声明为volatile后,每一个线程操做共享变量后就会当即同步到主存中,此功能是底层硬件支持的。也就是说volatile关键字解决了共享变量的可见性问题,但没有解决变量的原子性以及互斥性。 原子类中的变量所有声明为volatile,保证线程可见性,原子类使用cas算法保证原子性。java
public class VolatileDemo { public static void main(String[] args) { ThreadClass threadClass = new ThreadClass(); Thread thread = new Thread(threadClass); thread.start(); while (true){ if (threadClass.shareVar){//在这里main线程访问共享变量,该共享变量是main线程的变量副本 System.out.println("ShareVariableClass.shareVar:" + threadClass.shareVar); break; } } } } class ThreadClass implements Runnable{ public volatile boolean shareVar = false; @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } this.shareVar = true; System.out.println("sharVar change to " + shareVar); } }
结果以下,结果中打印的顺序会不一致。算法
CAS:全称compare and swap,比较并交换。当多个线程操做共享变量的时候,每一个线程的操做都写入主存中,就会致使主存中的共享变量不可以保证原子性。若是要操做一个变量s进行+1操做,在+操做以前,获取主存中s的值(经过volatile关键字保证可见性)做为指望值expectValue,将s进行+1操做后,写入主存以前经过将目前的主存值和expectValue值作比较,若是相同则将s+1的值写入主存,若是不相等,则重复进行上述步骤。缓存
以AtomicInteger举例ide
AtomicInteger atomicInteger = new AtomicInteger(10); int andIncrement = atomicInteger.getAndIncrement();
cas操做最终调用的方法是Unsafe类中的native方法调用,除了Integer类型的原子操做,还有Boolean等的类型操做,但调用是以下三个方法来保证原子性。boolean类型是经过转换为int类型来进行操做的。
this
全部原子类以下atom