目录
简单说下你对线程和进程的理解?
进程:就是在内存中运行的应用程序,一个进程可以有多个线程,比如微信,qq都是一个进程
线程:就是进程中的具体执行任务,负责当前进程中程序的执行,多个线程可共享数据。
进程 → 火车,线程 → 车厢;线程在进程下行进(单纯的车厢无法运行)
守护线程和用户线程的区别?
用户 (User) 线程:
- 运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程以及普通自定义线程等都是用户线程
守护 (Daemon) 线程:
- 运行在后台,为其他前台线程(非守护线程)服务。当所有用户线程都结束运行时,守护线程会随 JVM 一起结束工作.
- 可见,守护线程是依赖于用户线程,当所有用户线程都退出了,守护线程也就会退出,典型的守护线程如垃圾回收线程。
- 而用户线程是独立存在的,不会因为其他用户线程退出而退出。
二者其实基本上是一样的。唯一的区别在于JVM何时离开。
用户线程:当存在任何一个用户线程未离开,JVM是不会离开的。
守护线程:如果只剩下守护线程未离开,JVM是可以离开的。
- 注意: 默认情况下启动的线程是用户线程,通过setDaemon(true)将线程设置成守护线程,但必须在
start()
方法前执行,否则会抛出IllegalThreadStateException
异常 - 在守护线程中产生的新线程也是守护线程
- 守护 (Daemon) 线程中不能依靠 finally 块的内容来确保执行关闭或清理资源的逻辑。因为我们上面也说过了一旦所有用户线程都结束运行,守护线程会随 JVM 一起结束工作,所以守护 (Daemon) 线程中的 finally 语句块可能无法被执行。
什么是线程死锁?
死锁是指两个或多个进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,程序就会永远卡在那里
// 示例来自《并发编程之美》
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "线程 2").start();
}
}
形成死锁的四个必要条件是什么?
互斥: 某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。等待其他进程释放该资源。
不可抢占: 别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
循环等待: 存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。头尾相接的循环等待资源关系
我们该如何避免死锁?
死锁预防:----- 确保系统永远不会进入死锁状态
从四个必要条件下手
打破互斥条件
:改造独占性资源为虚拟资源,不过大部分资源已无法改造,一般从另外仨下手。- 破坏“占有且等待”条件:一次性申请全部资源条件
- 破坏不可抢占:/满足两个剩下一个未满足,则释放手里的资源条件
- 破坏循环等待:对资源进行编码,当一个进程占有编号为i的资源时,那么它下一次申请资源只能申请编号大于i的资源
死锁避免和死锁预防有啥不同?
死锁预防,至少破坏四个必要条件之一,严格的防止死锁的出现;死锁避免就是没有那么严格的限制产生死锁的必要条件的存在,即使死锁的必要条件存在,也不一定发生死锁,死锁避免是在系统运行过程中利用额外的检验信息,在分配资源时判断是否会出现死锁,只在不会出现死锁的情况下才分配资源。