进程和线程的概述
进程和线程的介绍
进程是操作系统进行资源分配和调度的基本单位。每个进程拥有独立的地址空间、内存、文件句柄等资源,相互隔离。例如,运行一个浏览器和一个文本编辑器就是两个独立的进程。进程的创建和切换开销较大,因为涉及资源分配。
线程是进程内的执行单元,也被称为轻量级进程。一个进程可以包含多个线程,这些线程共享进程的资源(如内存和文件),但每个线程有自己的程序计数器、栈和寄存器。线程使得程序能并发执行任务,例如在一个Web服务器中处理多个客户端请求。
主要区别:
- 资源隔离:进程间资源独立,线程共享进程资源。
- 开销:进程创建和切换成本高(涉及内存分配),线程成本低(只需少量栈空间)。
- 通信:进程间通信(IPC)需通过复杂机制(如管道或消息队列),线程间通信可直接通过共享内存。
- 容错:一个进程崩溃不影响其他进程,但一个线程崩溃可能导致整个进程终止。
线程状态介绍
在编程语言(如Java)中,线程的生命周期包括以下状态:
- 新建(New):线程对象已创建,但未调用
start()方法。 - 就绪(Runnable):线程已启动,等待CPU调度执行(进入运行状态)。
- 运行(Running):线程正在执行代码,占用CPU资源。
- 阻塞(Blocked):线程等待获取锁(如进入同步块时锁被占用)。
- 等待(Waiting):线程无限期等待其他线程的通知(如调用
wait()方法)。 - 计时等待(Timed Waiting):线程等待指定时间(如调用
sleep(ms)或wait(timeout))。 - 终止(Terminated):线程执行完毕或异常结束,无法重启。
线程状态转换由操作系统调度器或同步机制(如锁)控制。例如,从运行状态调用sleep()会进入计时等待状态,时间结束后返回就绪状态。
sleep和wait的区别
sleep和wait都用于线程控制,但行为和作用不同:
sleep:
- 是
Thread类的静态方法(如Thread.sleep(long millis))。 - 使当前线程暂停执行指定毫秒数,但不释放任何锁。
- 用于时间延迟,不依赖其他线程。
- 示例(Java代码):
synchronized (lock) {Thread.sleep(1000); // 线程睡眠1秒,锁不释放 }
- 是
wait:
- 是
Object类的方法(如obj.wait())。 - 使当前线程等待,直到另一个线程调用相同对象的
notify()或notifyAll()。在等待期间释放锁。 - 用于线程间协作,必须在同步块(如
synchronized)中使用。 - 示例(Java代码):
synchronized (lock) {lock.wait(); // 释放lock的锁,等待通知 }
- 是
关键区别:
| 特性 | sleep | wait |
|---|---|---|
| 所属类 | Thread | Object |
| 锁释放 | 不释放锁 | 释放锁 |
| 使用场景 | 时间延迟 | 线程间协作(生产者-消费者) |
| 依赖 | 独立,无需其他线程 | 需其他线程调用notify() |
| 唤醒方式 | 时间结束自动唤醒 | 需显式通知唤醒 |
并发和并行的介绍
并发指多个任务在重叠的时间段内执行,但不一定是同时。在单核处理器上,通过时间分片(如线程切换)实现,任务交替执行。例如,一个单核CPU的Web服务器并发处理多个用户请求,每个请求看似同时响应,实际是快速切换执行。并发关注任务管理和逻辑上的同时性。
并行指多个任务真正同时执行,通常需要多核处理器或多台机器。例如,在多核CPU上,多个线程并行计算矩阵乘法,每个核独立运行一个线程。并行关注物理上的同时执行,以提升性能。
区别:
- 执行方式:并发是逻辑同时(交替执行),并行是物理同时(同时执行)。
- 硬件需求:并发可在单核实现,并行需多核或多处理器。
- 应用场景:并发用于提高响应性(如UI线程和后台任务),并行用于加速计算(如大数据处理)。
- 性能模型:并行可线性提升速度(如n个核处理n个任务),并发优化资源利用率。
在编程中,并发通过线程或异步机制实现,并行通过多线程在多核系统上实现。例如,并发编程模型(如Actor模型)处理任务调度,并行算法(如MapReduce)利用多核资源。