一、java基础十大问
本文为简单总结,详细qhttps://www.cnblogs.com/dolphin0520/p/3920373.html
1、volatile关键字
volatile关键字主要用来修饰需要多线程访问共享变量,其主要作用有:
1)可见性
java虚拟机的内存模型决定每个线程并不是直接操作主内存,而是都有主内存的副本,即自己的工作内存,这样如果多个线程同时修改主内存中的一个共享变量时,其实是先在自己工作内存中进行,修改后再写入到主内存中。但如果线程1在工作内存中修改后还没有写入主内存时,线程2去读取时,仍然是未修改的值,就会导致错误。
如果增加volatile修饰,则线程1在工作内存修改后会立即写入主内存中。就不会出现多线程修改后不一致的情况。
2)有序性
编译器在处理指令时会进行优化,并不是按照代码书写的顺序执行,在单个线程中指令重排不会影响最终结果,但是如果多线程中执行时,并且是共享变量,会导致指令重排结果不正确,比如常用判断线程结束:
//线程1:
context = loadContext(); //语句1 共享变量
inited = true; //语句2 共享变量
//线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);
语句1和语句2没有依赖性,是会发生指令重排序的,如果发生重排序,线程1先执行语句2,线程2执行到while语句时,判断是true,就doSomethingwithconfig,其实并没有初始化完成。
3)volatile会保证原子性吗?
请分析以下哪些操作是原子性操作:
1 2 3 4 |
|
只有语句1是原子性的,语句2是先读取x值,然后再将x值写入到工作内存中赋值给y;语句3是先读取x值,进行加1后,再重新写回;同样的,x++和 x = x+1包括3个操作:读取x的值,进行加1操作,写入新的值。
Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,那么自然就不存在原子性问题了,从而保证了原子性。