Java-多线程
2021-01-23 07:12
标签:wait 数据区 异常 数组 指定 stat erro 任务 demo1 进程是系统运行程序的基本单位,在Java中启动一个main函数就是启动一个JVM进程,main函数所在的线程叫主线程. 线程是一个比进程还小的执行单位,一个进程可以产生多个线程. 总结 : 进程间是互相独立的,线程间是共享进程的空间,所以线程会有并发问题. 主要有2个作用: 线程私有,Java内存大致可以分为堆区和栈区,栈区指的就是虚拟机栈,一般用来局部变量. 虚拟机栈可以出现的异常: 线程私有,和虚拟机栈类似,区别是主要为 Native 方法服务. 虚拟机管理的内存中最大的一块,线程共享.垃圾回收管理的主要区域,所以也成为GC堆.几乎所有的对象实例以及数组都在这分配内存. 线程共享,主要存放被虚拟机加载的类的信息,常量,静态变量等. 这两个栈都是用来存放局部变量的,所以私有是为了防止别的线程访问到当前线程的局部变量. 当一个线程的时间片用完的时候就会变成就绪态,让其他线程使用,这个过程就是一次上下文切换. 线程1拥有资源A,线程2拥有资源B,此时线程1去申请资源B,由于B已经被线程2持有,所以线程1进入阻塞等待状态,并且不会主动释放所持有的资源A,这就叫死锁. 产生死锁的条件: 避免死锁,破坏条件: synchronized 关键字的底层原理? Java-多线程 标签:wait 数据区 异常 数组 指定 stat erro 任务 demo1 原文地址:https://www.cnblogs.com/qifengle1412/p/12885440.html多线程
JVM
线程私有 : 程序计数器,虚拟机栈,本地方法栈
线程共享 : 堆,方法区,直接内存
1. 字节码解释器通过改变程序计数器来决定下一条指令,从而控制代码流程.
2. 多线程情况下,程序计数器用来记录当前线程执行的位置,当线程切换回来的时候可以继续之前的流程,所以程序计数器是私有的.
1. StackOverFlowError 当前线程请求栈的深度超过了虚拟机栈的最大深度.
2. OutOfMemoryError 当请求栈时,内存用完了且无法拓展时.
多线程
调用start()时,会启动一个线程,当线程获得CPU时间时执行run()里面的内容;直接调用run(),会把run()当初main()下的一个普通方法去执行.
//假设 Demo 类的 demo() 被 synchronized 修饰
//例1 : 线程1,2抢占的是同一把锁,只能有一个线程持有.
public static void main(String[] args) {
Demo demo = new Demo();
Thread thread1 = new Thread(new MyThread(demo));
Thread thread2 = new Thread(new MyThread(demo));
thread1.start();
thread2.start();
}
//例2 : 线程1,2抢占的是两把锁
public static void main(String[] args) {
Demo demo1 = new Demo();
Demo demo2 = new Demo();
Thread thread1 = new Thread(new MyThread(demo1));
Thread thread2 = new Thread(new MyThread(demo2));
thread1.start();
thread2.start();
}
修饰静态方法后上面不论是例1还是例2都是抢占一个锁.
synchronized 关键字属于JVM层面.
通过查看字节码信息可以发现, synchronized 锁定代码的前后分别是 monitorenter 和 monitorexit ;当执行 monitorenter 时,线程去尝试获取锁(monitor,它存在于每个Java对象的头部,
所以Java对象都可以作为锁.),当计数器为0时获取成功,然后将计数器加1;执行 monitorexit 时,计数器减一. 如果锁获取失败,那么当前线程就一直等待,直到锁被另一个线程释放.