以下内容源于网络资源的学习整理,如有侵权,请告知删除。
参考博客
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)。
二、对比进程与线程
三、进程、线程的补充说明
(1)线程理解
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,是 CPU 调度的一个基本单位。
(2)线程和进程大致的区别
进程的执行过程是线状的,尽管中间会发生中断或暂停,但该进程所拥有的资源只为该线状执行过程服务。一旦发生进程上下文切换,这些资源都是要被保护起来的。这是进程宏观上的执行过程。
进程又可有单线程进程与多线程进程两种。单线程进程的执行过程在宏观上是线性的,微观上也只有单一的执行过程;而多线程进程在宏观上的执行过程同样为线性的,但微观上却可以有多个执行操作(线程),如不同代码片段以及相关的数据结构集。线程的改变只代表了 CPU 执行过程的改变,而没有发生进程所拥有的资源变化。除CPU 之外,计算机内的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
我们知道,进程有一个进程控制块 PCB、相关程序段、(该程序段对其进行操作的)数据结构集。与进程控制表和 PCB 相似,每个线程也有自己的线程控制表 TCB ,而这个TCB 中所保存的线程状态信息则要比 PCB 表少得多,这些信息主要是相关指针用堆栈(系统栈和用户栈),寄存器中的状态数据。
进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
线程可以有效地提高系统的执行效率,但并不是在所有计算机系统中都是适用的,如某些很少做进程调度和切换的实时系统。使用线程的好处是有多个任务需要处理 机处理时,减少处理机的切换时间;而且,线程的创建和结束所需要的系统开销也比进程的创建和结束要小得多。最适用使用线程的系统是多处理机系统和网络系统 或分布式系统。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
(3)摘取自http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html的评论区
四、多进程的代码示例
#include
#include
#include
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 ); 需要的参数是函数的调用地址。
五、多线程的代码示例