目录
1.线程通信
大部分场景下,几个线程之间是需要协调配合工作,一起完成一个总目标的。
协调配合工作就需要线程之间进行数据交换。
由于我们的线程都属于同一个进程,所以,共同享有 OS 分配过来的同样的资源(其中优先关注 内存资源)
2.JVM 下的内存区域划分
- PC 保护区(PC)
- 栈:虚拟机栈、本地方法栈
- 堆
- 方法区
- 运行时常量池
这些资源是属于进程的,理论上来讲,却是这个进程下的所有线程的。这些内存,在线程中还会分配一次。
堆、方法区、运行时常量池是整个进程(JVM)只有一份。
对象是大家共有的、加载的类是大家共有的
PC (保存 PC 的值)、栈(虚拟机、本地方法栈)是每个线程独一份(各自有各自的)
1.为什么每个线程都有自己的 PC:
每个线程都是独立的执行流,下一条要执行的指令和其他线程无关,所以有自己的 PC
2.为什么每个线程都得有自己的 栈:
每个线程都是独立的执行流,有各自调用的方法链,有各自要处理的临时数据,所以栈也是独一份的
在代码中:
局部变量,保存在栈帧中,也就是保存在栈中,是线程私有的。A 创建的局部变量,只有 A 在用
类对象( Class 对象 关于类的对象)、静态属性,保存在方法区中,所以是线程之间共享的。前提是有访问权限
对象(对象内部的属性),保存在堆中,所以是线程之间共享的。前提是线程持有该对象的引用。
public class Main {
static class MyThread extends Thread{
@Override
public void run() {
int r = 0; // 这个 r 存在于子线程的 run 方法的栈帧中
for(int i = 0;i < 1000;i++){
r++;
}
// r 应该是1000
System.out.println(Thread.currentThread().getName() + ":" + r);
}
}
public static void main(String[] args) throws InterruptedException {
int r = 0; //这个 r 存在于主线程的 main 方法的栈帧中
MyThread t = new MyThread();
t.start();
t.join();
System.out.println(r); // r应该是 0
}
}
变量本质是对一块内存的抽象。两个 r 只是名字都叫 r,但不是同一块内存。