volatile的原理是什么?一般用在什么地方?

2020-04-15 18:42:15 java常见问答 7034

接触过java软件开发的小伙伴们,不清楚你们还记不记得一个叫volatile的类型修饰符呢?不管还记不记得,下面就一起跟小编看看volatile的原理是什么吧,随便了解一下volition它一般会用在什么地方呢?

首先我们可以简单概述一下,volatile是Java语言提供的一种轻量级的同步机制,如果拿它跟synchronized相比,我们会发现volatile更轻量级,在访问volatile变量的时候不会执行加锁的操作呢,所有也就不会使执行的线程阻塞问题。

至于原理我们可以从以下两个问题出发。

首先是可见性的问题。因为CPU每次执行指令的时候会对内存进行读写方面的操作,其实内存的读写速度要比硬盘的读写速度快多很多,可是指令的处理速度更快,那么从内存进行读写速度相对于指令执行的速度就相对慢了,所以CPU就会将线程用到的变量以及一些复杂的操作复制到缓存中处理,然后再把处理的结果写入到内存里面。可是对于多核CPU,线程可能运行在不同的CPU缓存里面,这样的话就没有办法保证线程的可见性。

下面是有序性问题。

int i = 0; //步骤1
int j = 1; //步骤2
i++; //步骤3
j++; //步骤4

我们可以这样理解,CPU为了保证性能或者说在多个线程存在的情况下面,对于指令的处理顺序可能会有一些变化,例如它可能先执行了步骤2,然后在执行步骤1,也可能先执行了步骤4,然后再执行步骤3。

如果一个变量赋予了volatile关键字,那么该变量对所有的线程都具有可见性,当一个线程修改了这个变量的值,那么编译器就不会将这个变量复制到缓存中,而且就直接在内存中操作,这样从内存中取到的volatile标识的变量就是最新的值,那么对其它线程可见也不奇怪了。

还有就是线程有序性。volatile可以禁止指令重排序,volatile标识的变量,就会有内存屏障,指令重排序的时候就不能把后面的指令重排序到内存屏障之前的位置,这样就保证不同的代码块只能串行执行,确不能同步执行,于是就保证了线程的有序性。

volatile缺点:volatile是不能保证原子性的,volatile可以配合synchronized保证原子性。

那么这样看来,volatile最适合使用的地方是一个线程写、其它线程读的场合,如果有多个线程并发写操作,仍然需要使用锁或者线程安全的容器或者原子变量来代替。

如果一个线程写、一个线程读,根据前面针对volatile的应用总结,那么此时可以使用volatile来代替传统的synchronized关键字来提升并发访问的性能。

其实Netty中大量使用了volatile来修改成员变量,如果理解了volatile的应用场景问题,读懂Netty volatile的相关代码还是比较简单的。

好了以上就有关volatile的所有内容了,还想了解更多java一些知识问答就请继续关注本站消息哦。