并发编程中volatile面试总结

本文详细解析了并发编程中的三个关键概念:原子性、可见性和有序性,介绍了volatile和synchronized的区别,以及它们如何影响多线程协作。重点讲解了volatile关键字的轻量级同步特性及其在保证数据一致性和内存屏障上的作用。
摘要由CSDN通过智能技术生成

并发编程的三要素

1)原子性:原子性是指一个或多个操作要么全部执行成功,要么全部执行失败。atomic类,synchronized

2)可见性:多个线程共同访问共享变量时,某个线程修改了此变量,其他线程能立即看到修改后的值(synchronized,volatile)

3)有序性:代码的执行顺序未必就是编写代码时候的顺序,由于JAVA内存模型允许编译器和处理器为了效率,进行指令重排序的优化。指令重排序在单线程内表现为串行语义,在多线程中会表现为无序。Volatile,synchronized,lock保证有序性

        Java内存模型JMM中规定所有的变量都存储在主内存中,每条线程都有自己的工作内存,线程的工作内存中保存了该线程所使用的变量从主内存中拷贝的副本。线程对于变量的读、写都必须在工作内存中进行而不能直接读、写主内存中的变量。同时,本线程的工作内存的变量也无法被其他线程直接访问,必须通过主内存完成

volatile关键字

volatile通常被比喻成"轻量级的synchronized",volatile是一个变量修饰符,只能用来修饰变量无法修饰方法及代码块等,保证可见性和有序性,并不保证原子性。

1)可见性:当对volatile变量执行写操作后,JMM会把工作内存中的最新变量值强制刷新到主内存,同时写操作会导致其他线程中的缓存无效,这样其他线程使用缓存时,发现本地工作内存中此变量无效,便从主内存中获取,(遵守了缓存一致性协议)把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中,其值在多个缓存中是可见的,实现了线程的可见性

2)有序性:禁止指令重排序我们在加了volatile指令修饰后,在汇编代码当中被volatile修饰的变量在被赋值之后会多了一个“lock addl $0x0,(%esp)”操作,这个操作相当于一个内存屏障Memory Barrier指令重排序时不能把后面的指令重排序到内存屏障之前的位置内存屏障分为两种:Load Barrier 和 Store Barrier即读屏障和写屏障,java的内存屏障通常所谓的四种即LoadLoad, StoreStore, LoadStore,StoreLoad实际上也是上述两种的组合,完成一系列的屏障和数据同步功能。

缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。

3)volatile为什么不能保证原子性

CPU有时间片的概念,获得时间片之后开始执行,在时间片耗尽之后,就会失去CPU使用权。在多线程场景下,由于时间片在线程间轮换,就会发生原子性问题。为了保证原子性,需要通过字节码指令monitorenter和monitorexit,但是volatile和这两个指令之间是没有任何关系的,所以,volatile是不能保证原子性的。

synchronized 关键字 和 volatile 关键字的区别

  1. volatile 关键字是线程同步的轻量级实现,所以volatile 性能肯定比synchronized 关键字要好。但是volatile关键字只能用于变量而,synchronized 关键字可以修饰方法以及代码块。
  2. volatile 关键字能保证数据的可见性和有序性,但不能保证数据的原子性, synchronized 关键字都能保证。
  3. volatile 关键字主要用于解决变量在多个线程之间的可见性,而synchronized 关键字解决的是多个线程之间访问资源的同步性.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值