线程可见性问题 volatile-final-static jvm(jit)缓存
# java 可见性问题
## 什么是可见性问题
> 一个线程写值(先写),子线程读(后读)值,读不到,就是线程的可见性问题
>高速缓存和指令重排会导致可见性问题
![image.png](https://cos.easydoc.net/31477061/files/km3blsdz.png)
## JVM的jit编译 和CPU 会导致 指令重排
### 什么是jit
![image.png](https://cos.easydoc.net/31477061/files/km3bz2k6.png)
> 程序运行的时候 对热点代码 进行编译升机(相当于把代码缓存起来) 不在去一次一次的读,就造成了,可见性问题。
## java 是脚本语言?还是编译语言
![image.png](https://cos.easydoc.net/31477061/files/km3cawdw)
## volatile解决线程可见性问题
![image.png](https://cos.easydoc.net/31477061/files/km3cgl7y.png)
![image.png](https://cos.easydoc.net/31477061/files/km3cij1e.png)
---
![image.png](https://cos.easydoc.net/31477061/files/km4fgv25.png)
## final
- Java中的String类就是一个final类
- 类的private方法会隐式地被指定为final方法。
- 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
- 很多时候会容易把static和final关键字混淆,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变
![image.png](https://cos.easydoc.net/31477061/files/km4fzd1e.png)
![image.png](https://cos.easydoc.net/31477061/files/km4frks9.png)
## static
- “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
- 方便在没有创建对象的情况下来进行调用(方法/变量)。
- 静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
- static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
![image.png](https://cos.easydoc.net/31477061/files/km4gjp31.png)
- 因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。