以下内容源于网络资源的学习整理,如有侵权,请告知删除。
参考博客
http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html(通俗理解)
https://blog.csdn.net/chen_geng/article/details/51613445(表格总结,推荐)
https://blog.csdn.net/java_zero2one/article/details/51477791(并发和并行)
https://www.cnblogs.com/reality-soul/p/6397021.html(单进程和多进程的代码示例)
https://blog.csdn.net/zqixiao_09/article/details/50298693
https://blog.csdn.net/linux0231/article/details/24523129
https://blog.csdn.net/earbao/article/details/53106419
之前关于进程的学习要点总结:https://pan.baidu.com/s/1dktsSp2D8YIinhD2DUdUYQ
一、并发、并行
(1)并发:是指一个处理器同时处理多个任务,是逻辑上的同时发生(即假象)。
- 程序假装同时执行多个操作(每个小时间片执行一个操作,多个操作快速切换执行)。
(2)并行:是指多个处理器(或者多核处理器)同时处理多个不同的任务,是物理上的同时发生。
(3)比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。
(4)
当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状态。这种方式我们称之为并发(Concurrent)。
当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
二、对比进程与线程
进程,process | 线程,thread | |
定义 | 资源(CPU时间、内存等)分配的最小单位 | 程序执行的最小调度单位 |
区别 | 1、独立的地址空间。每创建一个进程,就会给该进程分配一个4G的虚拟内存空间。 2、进程是建立在虚拟内存的基础之上的。 | 1、没有独立的地址空间(同一进程内的线程共享进程的地址空间)。 2、主要是为了将进程的资源申请和调度属性分开。 |
联系 | 1、一个进程有几个线程组成。 2、同一个进程中的多个线程之间可以并发执行。 3、一个线程死掉就等于整个进程死掉。 4、线程与同属一个进程的其他的线程共享进程所拥有的全部资源。 | |
OS而言 | 1、uCOS只有线程的概念。uCOS的整个程序可以理解为一个进程,而其中的任务(一个个函数)就可以理解为一个个线程,有自己的堆栈和局部变量,但没有单独的地址空间。 2、对于windows,linux等,其有进程和线程。 | |
线程的优势 | 一、优势 1、与进程相比,它是一种非常"节俭"的多任务操作方式。 (1)对进程而言,创建一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。 (2)对一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。
2、与进程相比,线程间的通信机制更方便。 (1)对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。 (2)对一个进程中的多个线程,由于它们共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。
3、提高应用程序响应。
4、使多CPU系统更加有效。
5、改善程序结构。
二、线程可以有效地提高系统的执行效率,但并不是在所有计算机系统中都是适用的,如某些很少做进程调度和切换的实时系统。使用线程的好处是有多个任务需要处理 机处理时,减少处理机的切换时间;而且,线程的创建和结束所需要的系统开销也比进程的创建和结束要小得多。最适用使用线程的系统是多处理机系统和网络系统或分布式系统。 | |
区分进程、用户线程、内核线程 | ||
uCOS/Linux状态区别 | 线程只有 3 个基本状态:就绪,执行,阻塞。 线程存在 5 种基本操作来切换线程的状态:派生,阻塞,激活,调度,结束。 |
进程至少有 5 种基本状态: 初始态,执行态,等待状态,就绪状态,终止状态。 |
三、进程、线程的补充说明
(1)线程理解
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,是 CPU 调度的一个基本单位。
(2)线程和进程大致的区别
进程的执行过程是线状的,尽管中间会发生中断或暂停,但该进程所拥有的资源只为该线状执行过程服务。一旦发生进程上下文切换,这些资源都是要被保护起来的。这是进程宏观上的执行过程。
进程又可有单线程进程与多线程进程两种。单线程进程的执行过程在宏观上是线性的,微观上也只有单一的执行过程;而多线程进程在宏观上的执行过程同样为线性的,但微观上却可以有多个执行操作(线程),如不同代码片段以及相关的数据结构集。线程的改变只代表了 CPU 执行过程的改变,而没有发生进程所拥有的资源变化。除CPU 之外,计算机内的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
我们知道,进程有一个进程控制块 PCB、相关程序段、(该程序段对其进行操作的)数据结构集。与进程控制表和 PCB 相似,每个线程也有自己的线程控制表 TCB ,而这个TCB 中所保存的线程状态信息则要比 PCB 表少得多,这些信息主要是相关指针用堆栈(系统栈和用户栈),寄存器中的状态数据。
进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
线程可以有效地提高系统的执行效率,但并不是在所有计算机系统中都是适用的,如某些很少做进程调度和切换的实时系统。使用线程的好处是有多个任务需要处理 机处理时,减少处理机的切换时间;而且,线程的创建和结束所需要的系统开销也比进程的创建和结束要小得多。最适用使用线程的系统是多处理机系统和网络系统 或分布式系统。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
(3)摘取自http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html的评论区
四、多进程的代码示例
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h> void print_exit()
{ printf("the exit pid:%d/n",getpid() );
} main ()
{ pid_t pid; atexit( print_exit ); //注册该进程退出时的回调函数 pid=fork(); if (pid < 0) printf("error in fork!"); else if (pid == 0) printf("i am the child process, my process id is %d/n",getpid()); else { printf("i am the parent process, my process id is %d/n",getpid()); sleep(2); wait(); }
}
运行结果:
i am the child process, my process id is 15806
the exit pid:15806
i am the parent process, my process id is 15805
the exit pid:15805
说明:
(1)fork函数,功能是产生子进程。fork失败返回-1,成功返回0。
fork产生子进程的体现,就是它会返回2次:
一次返回0,顺序执行下面的代码。这是子进程。
一次返回子进程的pid,也顺序执行下面的代码,这是父进程。
(2)wait表明父进程等待子进程的终结后,处理其task_struct结构,否则会产生僵尸进程。
(3)atexit( print_exit ); 需要的参数是函数的调用地址。
五、多线程的代码示例