Java内存模型
Java内存模型即Java Memory Model,简称JMM。
注意:Java内存模型不是像堆内存,方法区,栈内存类似的东西,这个叫Java内存结构。Java内存模型跟多线程有关。
java内存模型,决定一个线程是否与另外一个线程可见性,
在java内存模型中分为主内存(共享的变量)和私有本地内存(也可以叫工作内存,本地线程私有的变量)
主内存与工作内存:
Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。
在之前的买票例子中。
票的数量是100,那么就是count = 100,该数值是被存在主内存中。当其它线程过来读取时,会在自己私有本地内存中
开辟一块空间count = 100。
线程会先在本地内存中修改,然后再刷新到主内存中去,这时候就引发了线程安全问题了。
多线程安全三大特性
在我们编写多线程条件下,要保证3大特性:
- 原子性
一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。这2个操作必须要具备原子性才能保证不出现一些意外的问题。
A-1000;b+1000;
这行代码在Java中是不具备原子性的,则多线程运行肯定会出问题,所以也需要我们使用同步和lock这些东西来确保这个特性了。 - 可见性
当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 - 有序性
java语言规范规定JVM线程内部维持顺序化语义。即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执行顺序可以与代码顺序不一致,此过程叫指令的重排序。优点:JVM能根据处理器特性(CPU多级缓存系统、多核处理器等)适当的对机器指令进行重排序,使机器指令能更符合CPU的执行特性,最大限度的发挥机器性能。
int a = 10; //语句1
int r = 2; //语句2
a = a + 3; //语句3
r = a*a; //语句4
则因为重排序,他还可能执行顺序为 2-1-3-4,1-3-2-4
显然重排序对单线程运行是不会有任何问题,而多线程就不一定了,所以我们在多线程编程时就得考虑这个问题了。