简单了解volatile的概念。

一、实现原理

通过加入内存屏障、禁止重排序,实现内存可见性

volatile变量在每次被线程访问时,都强迫从主内存中重新读取该变量的值,而当该变量变化时,又会强迫线程将最新的值刷新到主内存。所以任何时刻,不同线程总能看到该变量的值。

二、存在的问题

输出为:

加入一个线程休眠100ms:

结果就是变成499,498,497…什么结果都有。

为什么?因为volatile不具有原子性。

number++操作实际如下:

  1. 在内存中读取number值。
  2. number+1。
  3. +1后的number值写回内存中。

就算有volatile,这段程序还是会有这种结果:

  1. 线程A读取number的值。
  2. 线程B抢走了CPU,线程A未执行完毕,B读取了number的值。
  3. 线程B执行了+1操作。
  4. 线程B写入了最新的number的值。现在主内存:number = 6,线程B工作内存number = 6,但是在线程A的工作内存中,number依然是5!
  5. 现在线程继续:线程A执行了+1的操作,根据线程A的工作内存,number为5。
  6. 线程A写入最新的number(5+1=6)

那么问题就出现了,执行了两次线程,number只加了一次为5。

三、解决方法

  1. 使用synchronized关键字。
  2. 使用ReentranLock(java.until.concurrent.locks包下)。
  3. 使用AtomicInterger(java.util.concurrent.atomic包下)。

(1)synchronized

test.java

等待synchronized这个锁的时候,等待时间会很长,所以记得移除sleep(100),除非你想等半天。

如果要缩小粒度锁,这样改:

这样既可以sleep也可以实现同步,速度又快又准确。

(2)reentranlock

先lock加锁,再写一个try…fianlly…语句块,把操作放在里面,在finally那里unlock解锁,就实现了lock里面的同步了。

如果只加锁不放锁,可能会产生一些异常,所以必须要规范。

四、总结

简单demo,粗略理解。

发表评论

电子邮件地址不会被公开。 必填项已用*标注