轻量级“锁” volatile
在Java的多线程并发中,少不了synchronized 和volatile,synchronized 是个重量级的,在使用上,肯定会有较大的一个消耗,这个时候,如果条件允许的话,我们就可以使用volatile来代替我们的synchronized ,实现性能上的优化
volatile是一个读安全,写不安全的角色
volatile是一个对变量修饰的关键字,就和static、final等一样,要使用的时候,写在共享变量的前面
private volatile int a;
volatile保证可见性
volatile保证了变量的可见性,在线程里面,CPU对变量的操作中,每一个线程,都会将变量复制一份到自己的CUP缓存里面,因为不这样做的话,每次CPU都需要到内存里面对变量进行读取,这样就造成了一个时间性能上的浪费,所以每一个线程都自己赋值一份到自己的缓存,这样,每一次的操作,都在缓存上操作,这样,就大大的节省了时间。
被volatile修饰的变量,当其中一个线程对其改变后,他会立即将改变的值返回到内存里面,将内存里面的值改变,而其他线程里的处理器,他时时刻刻都在嗅探着总线,当他发现自己的值过期后,当前在缓存里面的该变量缓存就变为了无效的状态,需要重新到内存里面读取,所以volatile修饰的变量对于每一个线程都是可见的,因为变量一旦改变了,其他线程就能马上发觉,而后里面修改自己的缓存,所以volatile保证了变量的可见性
volatile保证有序性
内存屏障:通俗的说,这就相当于一条围栏,他拦着两边的东西交换,这样就可以对内存的操作进行顺序限制
当两条指令想交换执行循序时(不影响程序执行结果),由于内存屏障的存在,他们变的无法交换,这样就实现了指令执行的有序性
volatile不保证原子性
因为volatile不保证原子性,所以,他是一个写不安全的,虽然是可见性的,可以让他改变后的值立刻更新到别的线程缓存,但是因为不具有原子性,所以,当某一个线程先读取了自己缓存里面的值后,才嗅探到数据已经被改变,但是因为数据已经读取到处理器里面计算去了,虽然缓存的数据已经被该改变,但处理器的数据还是过期的数据,如果具有原子性,那么因为缓存数据已经被该了,所以处理器的操作也将失败,因为原子性是不可中断的,一系列操作里面只要一步错了,那将全部失败,但是因为volatile不具有原子性,所以虽然缓存错了,但是处理器仍然可以执行,这样写完后,存回内存将造成一个错误的操作,所以
volatile是一个写不安全的