目录
僵尸进程、孤儿进程、守护进程的区别
分析
僵尸进程
(记忆点:儿子死了、爸爸没有收尸、儿子就成僵尸了):僵尸进程是指终止但还未被回收的进程。如果子进程退出、而父进程并没有调用 wait() 或 waitpid()
来回收、那么就会产生僵尸进程。
僵尸进程是一个已经死亡的进程、但是其进程描述符仍然保存在系统的进程表中。
危害:占用进程号、系统所能使用的进程号是有限的、可能导致不能产生新的进程、占用一定的内存。
如何避免产生僵尸进程:
-
父进程调用
wait
或者waitpid
等待子进程结束 -
子进程结束时、内核会发送
SIGCHLD
信号给父进程。父进程可以注册一个信号处理函数、在该函数中调用waitpid
、等待所有结束的子进程、也可以用signal(SIGCHLD, SIG_IGN)
忽略SIGCHLD
信号、那么子进程结束后、内核会进行回收 -
杀死父进程、僵尸进程就会变成孤儿进程、由 Init 进程接管并处理
孤儿进程
(记忆点:爸爸死了、就是孤儿):如果某个进程的父进程先结束了、那么它的子进程会成为孤儿进程。每个进程结束的时候、系统都会扫描是否存在子进程、如果有则用 Init 进程(pid = 1)
接管、并由 Init
进程调用 wait
等待其结束、完成状态收集工作。孤儿进程不会对系统造成危害。
守护进程:
守护进程(英语:daemon
)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。不与任何终端(控制台)关联。这意味着它们不会接收用户的直接输入、也不会将输出直接显示在终端上。它不需要用户输入就能运行而且提供某种服务、不是对整个系统就是对某个用户程序提供服务。Linux
系统的大多数服务器就是通过守护进程实现的。
守护进程的名称通常以 d 结尾、比如 sshd
、xinetd
、crond
等、常见的守护进程包括系统日志进程syslogd
、web
服务器 httpd
、邮件服务器 sendmail
和数据库服务器 mysqld
等。
守护进程主要作用是在后台持续运行,提供各种系统服务和执行自动化任务,而无需用户的直接干预。
如果没有守护进程、许多重要的系统功能和服务将无法正常运行、用户需要手动执行许多重复性的任务、这将大大降低系统的效率和可用性。
守护线程依赖于 JVM 中非守护线程(也称为用户线程)的生命周期。 由用户程序(通常是主线程)创建并启动。
在后台运行、执行一些辅助性的任务(例如垃圾回收线程、心跳检测线程,、 监控线程。)。当 JVM 中所有非守护线程都结束时、JVM 会自动退出、所有守护线程也会被强制终止。 即使守护线程还在执行任务、也会被强制停止。
守护线程的特点
-
生命周期:守护线程的生命周期依赖于创建它的用户线程、当最后一个用户线程结束时、守护线程会自动结束。
-
作用:守护线程通常执行一些低优先级的任务,如垃圾回收、对象销毁回收资源、日志监控等。
-
不适合:守护线程不适合执行读写操作或计算逻辑、因为它可能在操作未完成时JVM就退出了。
-
注意点:设置守护状态必须在启动线程之前进行、一旦线程启动、你不能更改其守护状态。
守护线程与用户线程的对比
-
终止时机:用户线程与程序的生命周期相同,即用户线程不结束,程序就不会终止;守护线程则是在所有用户线程都结束时自动终止。
-
任务性质:用户线程执行核心业务逻辑,而守护线程执行后台支持任务。
-
资源占用和优先级:守护线程通常优先级较低,并且不应该占用过多资源,因为它们在任何时候都可能被中断。
补充守护线程在分布式锁的运用:
首先来看问题:
面试问题:看门狗的异步线程是设计成守护线程吗
看门狗的异步线程是设计成守护线程吗?要不然万一主线程挂了、没有释放锁、那这个看门狗就会一直循环下去、给锁续约、那这个锁就永远无法释放了、看门狗也会变成一个死循环。
Redisson
的看门狗实现是守护线程。可以保证主线程挂掉后、看门狗的线程不会持续的执行下去。
Redisson 看门狗的作用: Redisson 是一个基于 Redis 的 Java 分布式对象和服务的一个框架。它提供了分布式锁的实现。 为了防止 Redis 客户端在持有锁期间崩溃、导致锁永远无法释放、Redisson
使用了一个看门狗线程来定期续约锁的过期时间。
为什么使用守护线程:
- 防止死锁: 如果看门狗线程不是守护线程、并且主线程崩溃、那么 JVM 不会退出。 看门狗线程会继续运行、不断地续约锁的过期时间、导致锁永远无法释放、从而造成死锁。
- 资源释放: 使用守护线程可以确保当主线程崩溃时、JVM 会退出、从而释放所有资源、包括锁。
守护线程的优势:
-
自动终止: 当所有非守护线程都结束时、JVM 会自动退出、从而终止看门狗线程。
-
资源清理: JVM 退出时会释放所有资源、包括锁。
-
防止死锁: 确保即使主线程崩溃、锁最终也会被释放
参考面试回答
-
僵尸进程是指子进程已经终止、但其父进程尚未调用
wait()
或waitpid()
函数来获取子进程的终止状态、导致子进程的进程描述符仍然保留在系统进程表中、成为僵死进程、僵死进程不占用系统资源、但会占用一个进程 ID。 -
孤儿进程是指父进程先于子进程退出或异常终止、导致了进程成为孤儿进程。孤儿进程会被
init
进程(进程 ID 为 1)接管、init
进程会成为孤儿进程的新父进程。 -
守护进程是在后台运行的一种特殊进程、不与任何终端关联、关闭终端并不会影响守护进程的生命周期。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程的生命周期通常与系统的生命周期相同、通常是伴随系统的启动和关闭、会一直在后台运行。