前言
java内存模型是什么样的?threadLocal的应用?volititle如何实现本地内存和住内存的数据同步?重排序?happensBefore原则是这节需要思考的问题。
JMM
java内存模型如上图所示,多个线程对共享变量没有直接采用加锁的方式,而是每个线程可以保留共享变量的副本。每个线程有一个工作内存,叫做threadLocal,共享变量存在threadlocal里的threadlocalMap中,在之后的博客中会详细讨论threadlocal及内存溢出问题。threadLocal之间与共享变量保持一致用的是volatile,工作原理简而言之是这样的,只要一个threadLocal里的变量改了,就会有监视器检测到,让cpu把新值强刷进主存。其他threadLocal在用到该 变量时应用的是CAS乐观锁来保持一致性,先拿自己工作内存中的变量值和主存中的变量值比较如果一样就用该值,如果不一样就用主存中的值替换掉工作内存中的值。
CAS,threadLocal会在之后的博客总详细讲解,这里就不细说了。
重排序
好的内存模型除了能存储并保证基本的一致性还要提高性能,所以为提高性能 ,编译器,处理器常常会对指令进行重排序。
1属于编译器重排序,2,3属于处理器重排序。有的时候会禁止一些特殊的编译器重排序,和通过插入内存屏障禁止处理器重排。因为重排序是为了提高运行效率,但是必须保证结果和顺序执行as-if-serial是一样的。比如两个操作,其中一个有写,读写,写读,写写都不可以重排序。
happensBefore原则
happensBefore原则和as-if-serial差不多,都是为了使程序在重排序后还是跟顺序执行一样,保证结果的正确性。不同的是as-if-serial是单线程里的,happensBefore是要保证多线程正确性的。比如a线程写操作a happensBefore b线程的读操作b,必须保证a的结果对b可见。
小结
java内存模型和jvm内存模型是不一样,要区分开。用下面的图做个总结: