做网站哪家最好,公司网站在百度搜不到,wordpress 客户端 出错,网站开发需要书籍1.什么是volatile volatile是 轻 量 级 的 synchronized#xff0c;它在多 处 理器开 发 中保 证 了共享 变 量的 “ 可 见 性 ” 。可 见 性的意思是当一个 线 程 修改一个共享变 量 时 #xff0c;另外一个 线 程能 读 到 这 个修改的 值 。如果 volatile 变 量修 饰 符使用…1.什么是volatile volatile是 轻 量 级 的 synchronized它在多 处 理器开 发 中保 证 了共享 变 量的 “ 可 见 性 ” 。可 见 性的意思是当一个 线 程 修改一个共享变 量 时 另外一个 线 程能 读 到 这 个修改的 值 。如果 volatile 变 量修 饰 符使用恰当的话 它比 synchronized 的使用和 执 行成本更低因 为 它不会引起 线 程上下文的切 换 和 调 度。 2. volatile的工作原理 java的内存模型 每个线程会有个相互独立的本地内存本地内存中存放的是的主共享中变量的副本,线程操作这些副本,然后不定时的将他们返回给主内存中 使用volatile 如果被volatile修饰会通过嗅探立刻返回给主内存 当某个线程把volatile修饰的变量从本地内存返回给主内存时其他的本地内存保存的该变量无效,当然不能保证写后读,因为如果两线程都在写入的过程中时,还是会产生覆盖的 3. volatile的作用 volatile只能用来修饰变量在并发编程的三大特性——原子性、可见性、有序性中 volatile只能保证可见性和有序性禁止指令重排[防止修饰的对象上一行下一行不重排序]并不能保证原子性而synchronized这三种特性都可以保证。 为什么没有保证原子性 a的过程 读取a的当前值。将读取到的值增加1。(此时还没有写入到a)将新值写回到a 例如a被volatile修饰了,代码中定义了a 可以看做(int k a1; ak)的过程; 这段代码中只能保证k读取的时候a是最新值不能保证写回a的时候a是最新值(因为当前线程刚执行完1,2步还没执行3,切换了时间片,此时并没有修改a的值所以不会写回到主内存)另一个线程执行了完整的1,2,3并放入主内存中此时本地内存也会修改接下来又切换回时间片执行将新值写回到a又回了主内存此刻就产生了并发问题(如果还是想不通,可以想象3个线程下,第三个线程可能会读取到旧的值) 当然指使用volatile并不能保证线程安全,需要结合CAS失败重试策略,来保证线程安全的 4. 为什么使用了synchronized还需要volatile 用单例举例 public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton null) { synchronized (Singleton.class) { if (singleton null) { singleton new Singleton(); } } } return singleton; }
} singleton new Singleton() 在我们看来就是一句话操作而已但在虚拟机看来它一共分为了几个指令操作 为对象分配内存空间初始化对象将引用指向对象的内存空间地址 虚拟机执行的时候不一定是按顺序123的执行也有可能是132。这是虚拟机的重排序引起的单线程情况下是没有什么bug的最终都会创建出对象只是先后顺序不同。 但是在上面例子中会出现这么一种情况 假如线程A执行 single new Single()虚拟机是按132排序执行当执行到3的时候single 引用已经不为空。此时若线程B执行到第一次验校处(第一次验校不在同步代码中因此所有线程随时都可以访问)它判断 single null 得到false,直接返回single对象。但是此时single对象还没初始化完成因此很有可能就会发生bug。 在上诉单例模式中volatile保证了虚拟机执行字节码的时候指令不会重排序。