从[深入理解Java虚拟机],[Java并发编程的艺术]这两本书里学到了很多知识。
在学习的过程中,总结下对多线程的理解。多线程的底层原理非常复杂,个人也在不断学习当中,这篇文章也只是管中窥豹,难免有错误的地方。
这篇文章希望能对以下几个问题有疑惑的人有所启发:
- 对象为什么会不安全?
- Java多线程之间怎么相互通信?
- 开发人员怎样判断对象在多线程环境下是否安全?
- 开发人员怎么编写正确的高并发代码?
JVM的内存区域
首先看下JVM(java虚拟机)运行时的数据区域的划分:
图中的这些区域都有各自的用途以及生命周期,简单了解下:
方法区:Method Area是各个线程共享的内存区域,它用来存储被jvm加载的类信息,常量,静态变量等数据。我们经常提到的常量池就存放在这里。
堆:Java Heap用来存放所有对象的实例,由所有线程共享。JVM规范中指出所有的对象实例以及对应的数组实例都在堆中分配。堆是jvm内存中最大的一块区域,也是GC(Garbage Collected)垃圾回收机制作用的主要区域。
程序计数器:每一个线程都各自拥用有独立的计数器,用来存储所执行的字节码的行号。当多线程相互交替执行的时候,各自线程依靠它来选取下一条需要执行的字节码指令。(你可以把它当作一个标记,当线程被其他线程抢占了cpu,也就是阻塞的时候,会记录下当前执行到的字节码行号。当该线程重新可执行的时候,它就知道从哪开始执行了)
栈:虚拟机栈是用来存储Java方法执行的区域。解释下这句话:每个方法在执行的时候都会创建一个栈帧(一种数据结构),栈帧里存储了局部变量表,对象引用,操作数栈,方法出口等信息。每一个方法从开始到执行结束的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
再看下面的代码:
public class Demo {