1、进程和线程
1.1、基本概念
线程(Thread)和进程(Process)是操作系统中重要的概念,用于管理程序的执行和资源分配。它们是多任务处理的基本单位,但在概念上有一些不同之处。
进程(Process):
- 进程是程序执行的一个实例。它包括了程序的代码、数据以及程序执行时所需的各种系统资源(如内存、文件句柄等)。
- 每个进程都有独立的内存空间,因此它们之间不能直接共享数据,通信需要通过特定的机制来进行(如进程间通信)。
- 进程是相互独立的,一个进程崩溃通常不会影响其他进程。
- 操作系统会为每个进程分配一定的资源,如内存空间、文件描述符等。
线程(Thread):
- 线程是进程内的一个执行单元,它可以与同一进程中的其他线程共享同一地址空间和其他资源。
- 同一进程内的多个线程共享该进程的资源,因此线程间的通信和数据共享相对容易。
- 线程可以看作是轻量级的进程,创建和销毁线程的开销通常比创建和销毁进程要小得多。
- 多线程的应用程序可以更有效地利用多核处理器的计算能力,因为不同的线程可以在不同的处理器核心上并行执行。
1.2、区别与联系
进程通常包含一个或多个线程。进程是程序的执行实例,而线程是进程内的执行单元。在现代操作系统中,一个进程可以有一个或多个线程,这些线程共享该进程的资源,如内存空间、文件句柄等。每个线程都可以执行不同的任务,但它们共享进程的上下文和资源,因此可以更有效地完成多任务处理。
1.3、相关案例
例如浏览器,每次你打开一个新的标签页或者一个新的窗口,操作系统都会为其分配一个新的进程。每个标签页可以运行在一个单独的进程中,一个标签页崩溃时不会影响其他标签页。而在浏览器运行时,可能有一个线程用于处理用户界面的操作,另一个线程用于下载和渲染网页内容,还有一个后台线程用于处理网络请求。
1.4、扩展:线程,进程与cpu的联系
进程:
- 进程是程序的执行实例,是 CPU 资源分配的基本单位。
- 操作系统通过调度算法将 CPU 时间分配给不同的进程,以便它们可以执行任务。
- 每个进程都有自己独立的内存空间和资源,包括代码、数据、打开的文件等。
线程:
- 线程是进程内的执行单元,是 CPU 调度的基本单位。
- 在同一个进程内,多个线程共享该进程的资源,包括内存空间、文件句柄等。
- 多线程应用程序可以更有效地利用 CPU 的多核处理能力,因为不同的线程可以并行执行在不同的 CPU 核心上。
上面提到,多线程应用程序可以更有效地利用 CPU 的多核处理能力,因为不同的线程可以并行执行在不同的 CPU 核心上。由此可以引出并发与并行的概念。
2、并发与并行
2.1、基本概念
简单来说:并发是多个任务在同一时间间隔内交替执行,而并行是多个任务在同一时刻同时执行。在实际应用中,这两个概念通常会同时存在,因为系统可能会同时利用并发和并行来提高性能。
2.2、区别与联系
并发(Concurrency):
- 并发指的是在同一时间间隔内执行多个任务,但这些任务不一定同时进行。它们可能交替执行,由系统的调度算法决定哪个任务在某个时刻执行。
- 并发通常用于描述多个任务在一个处理器上交替执行,通过快速地切换任务的执行状态来模拟多个任务同时运行的效果。
- 并发使得系统能够更高效地利用资源,处理多个任务,提高系统的响应速度。
并行(Parallelism):
- 并行指的是在同一时刻同时执行多个任务,这些任务可以在多个处理器核心上并行执行,每个任务都在独立的处理器核心上运行。
- 并行通常用于描述多个任务真正同时执行的情况,每个任务都在其自己的处理器核心上运行,互相之间不会影响或阻塞。
- 并行可以实现更高的性能和吞吐量,尤其在需要处理大量计算密集型任务时效果更为显著。
2.3、相关案例
厨房中的烹饪:当你在厨房里做饭时,可能同时进行多项任务,比如煮面、炒菜、准备配菜等。虽然每项任务可能需要一段时间来完成,但你可以交替执行它们,从而在相对较短的时间内完成整顿饭菜。与交替执行相对的是顺序执行,比如先煮面,然后炒菜,最后准备配菜。这称之为串行。
家庭成员分工合作:在家庭中,不同的家庭成员可以分工合作,同时进行不同的任务。例如,一个人可以准备晚餐,另一个人可以打扫卫生,还有人可以帮助孩子完成作业。这样每个人都在同时进行自己的任务,以提高效率并节省时间。
2.4、cpu核心与并发并行
单核 CPU 上的并发通过时间分片(Time Slicing)来实现,即在不同的时间段内切换执行不同的任务,从而模拟多个任务同时执行的效果。
多核 CPU 提供了真正的并行执行能力,每个核心可以独立执行不同的任务,而不会相互干扰。
当系统具有多个 CPU 核心时,可以通过并行来实现多个任务的真正同时执行,每个任务在不同的核心上并行运行,互不干扰。
在单核 CPU 上,虽然不能实现真正的同时执行,但可以通过并发来模拟多个任务同时运行的效果,通过时间分片在不同任务间切换,从而实现多任务处理。
多核 CPU 在并行执行任务时通常比单核 CPU 具有更高的性能和吞吐量,因为它们可以同时处理多个任务,提高了系统的并行处理能力。
3、同步与异步
3.1、基本概念
同步(Synchronous):任务按照顺序依次执行,每个任务的执行都是依赖前一个任务的完成。在同步执行中,一个任务的执行可能会阻塞后续任务的执行,直到该任务完成。
异步(Asynchronous):异步指的是任务可以同时进行,不必等待前一个任务的完成。在异步执行中,任务的提交和执行是分开的,任务可以并行执行,不会阻塞其他任务的执行。异步任务通常会在后台执行,并且在完成后会通知调用者或执行回调函数。
同步和异步强调任务的等待方式,而并发和并行强调任务的执行状态。
Q1:这里提到的异步,与上节的并发,并行有什么联系和区别?
同步和异步强调任务的等待方式,而并发和并行强调任务的执行状态。异步操作可以通过并发来实现。例如,使用多线程或回调函数实现异步操作时,可以利用并发的特性,让任务在后台执行,不会阻塞主线程的执行。在某些情况下,异步操作也可以实现并行执行。例如,在拥有多个处理单元的系统中,异步任务可能会被分配到不同的处理单元上执行,从而实现并行执行的效果。
并发和并行是异步操作的两种可能的执行状态。异步操作可以并发执行,也可以并行执行,具体取决于系统的硬件资源和任务的性质。
3.2、相关案例
文件读取操作:
- 同步:在同步文件读取中,程序会在读取文件时等待文件读取完成后再继续执行后续操作。这意味着程序在读取文件期间会被阻塞,直到文件读取完成。
- 异步:在异步文件读取中,程序会发起文件读取请求,然后继续执行后续操作,而不必等待文件读取完成。当文件读取完成后,程序会收到通知或执行回调函数来处理文件读取结果。
网络请求操作:
- 同步:在同步网络请求中,程序会在发送网络请求后等待服务器响应,直到收到完整的响应数据后再继续执行后续操作。这意味着程序在等待服务器响应期间会被阻塞。
- 异步:在异步网络请求中,程序会发起网络请求,并继续执行后续操作,而不必等待服务器响应。当服务器响应返回后,程序会收到通知或执行回调函数来处理响应数据。
虽然异步可以提高执行效率,但并非任何时候都无脑异步,还需考虑到具体的业务场景。
3.3、异步可能导致的问题
- 竞态条件(Race Conditions):当多个异步操作同时访问或修改共享的资源时,可能会出现竞态条件,导致未定义的行为或数据一致性问题。例如,如果两个异步任务同时尝试写入同一文件,可能会导致数据损坏或丢失。(幂等性)
- 死锁(Deadlocks):异步操作中可能存在资源的循环依赖,导致程序中的死锁。例如,当一个异步任务等待另一个任务的结果,而后者又依赖于前者的结果时,可能会发生死锁,导致程序无法继续执行。
- 内存泄漏(Memory Leaks):在异步操作中,如果不正确地管理资源的生命周期,可能会导致内存泄漏问题。例如,如果异步任务持续创建新对象而不释放资源,可能会导致内存使用量不断增加,最终耗尽系统内存。(例如阿里代码规范中线程池相关操作)