02 volatile

关键字volatile

1.多线程的三个特性?
  • 原子性:是指一个操作是不可中断的。即使是多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
  • 可见性:是指当一个线程修改了某一个共享变量的值,其他线程能够立即知道这个修改。
  • 有序性:在并发时,程序的执行可能会出现乱序。有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。
2.产生线程可见性的原因?保证线程可见性有哪些方法
  • 每个线程都在自己的缓存中保存着共享变量的副本,一个线程对共享变量进行更改,其他线程可能不会意识到这个改动,读取的还是自己缓存中的数据,这就产生了可见性问题。
  • volatile、synchronized、Lock
3.volatile的作用
  • 保证内存可见性(但不保证操作的原子性)。
  • 防止指令重排。
4.volatile用法

当多个线程操作同一个变量时,每个线程将拥有那个变量的本地缓存拷贝,因此,当某一个线程修改了这个变量的值时,实际上修改的是它本地缓存中的变量值,而不是主内存中的变量值,而其他线程并不知道这个变量的值被改变了。为了避免这种情况,我们可以用 volatile 关键字声明这个变量,当一个变量被声明为 volatile 后,java 内存模型确保所有使用该变量的线程能看到相同的、一致的值。

5.volatile如何保证可见性?(可见性的具体实现)(变量更新会直接同步到主存,并另其他线程的变量无效)

如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,当CPU发现这个指令时,立即做两件事:

  1. 将当前线程该变量缓存的数据立刻回写到系统内存。
  2. 这个写回内存的操作会使在其他线程里缓存了该内存地址的数据无效。
6.volatile如何通知其他线程有数据变化?

  如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将当前线程该变量缓存的数据立刻回写到系统内存。(每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里)缓存一致性协议

7.volatile的优点和缺点?
  • volatile的好处:volatile是一种非锁机制,可以避免锁机制引起的线程上下文切换和调度问题。因此,volatile的执行成本比synchronized更低。
  • volatile的不足:使用volatile关键字,可以保证可见性,但是却不能保证原子操作
8.volatile和synchronized区别?

volatile与synchronized都用于保证多线程中数据的安全

  1. volatile本质是在告诉jvm当前变量在缓存中的值是不确定的,需要从主内存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
  2. volatile仅能用在变量级别,而synchronized可用在变量和方法中
  3. volatile不需要加锁,因此不会造成线程的阻塞,相比synchronized更轻量级,而synchronized可能导致线程的阻塞
  4. volatie能保证变量的修改可见性,但是无法保证变量操作的原子性。而synchronized可以保证变量的修改可见性与原子性
  5. volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.
9.volatile为什么不能保证原子性
  • Java中对基本类型变量的赋值和读取是原子操作,但是像i++这样的操作就不是原子操作,因为进行了多次原子操作,比如先读取i的值,再将i+1的值赋值给i,多个原子操作加起来就不是原子操作了,所以即便是volatile具有可见性,也不能保证对它修饰的变量具有原子性。
  • 一个变量i被volatile修饰,两个线程想都对其进行i++操作,i++的过程可以分为三步,首先获取i的值,其次对i的值进行加1,最后将得到的新值写回到缓存中。
    线程A首先得到了i的初始值100,但是还没来得及修改,就阻塞了,这时线程B它也得到了i的值,由于i的值未被修改,那么线程B得到的值也是100,之后B对它进行加1操作,得到101后,并且将新值写入到缓存中,再刷入主存中。这时线程A继续执行,由于线程A之前已经读取到了i的值为100,也就是说读取的这个原子操作已经结束了,所以A继续将100这个值加1,得到101,再将值写到缓存,最后刷入主存,所以即便是volatile具有可见性,也不能保证对它修饰的变量具有原子性。
10.volatile是怎么样保证有序性的?

volatile关键字能禁止指令重排序

  1. 当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
  2. 在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
11.volatile可以用在哪些地方?
  1. 中断服务程序中修改的供其它程序检测的变量需要加volatile;
  2. 多任务环境下各任务间共享的标志应该加volatile;
  3. 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值