java面试总结--【1】volatile关键字

一、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

x = 10;         //语句1

y = x;         //语句2

x++;           //语句3

x = x + 1;     //语句4

只有语句1是原子性的,语句2是先读取x值,然后再将x值写入到工作内存中赋值给y;语句3是先读取x值,进行加1后,再重新写回;同样的,x++和 x = x+1包括3个操作:读取x的值,进行加1操作,写入新的值。

Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,那么自然就不存在原子性问题了,从而保证了原子性。

猜你喜欢

转载自blog.csdn.net/zht245648124/article/details/90521570
今日推荐