精华内容
下载资源
问答
  • 进程和线程区别,最简单的解释说明

    万次阅读 多人点赞 2019-05-16 14:52:10
    2、进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段数据段,这种操作非常昂贵。 而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的...

    1、进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)


    2、进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
    而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。


    3、线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。


    4、但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

     

    根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。

    java基础教程:https://ke.qq.com/course/149432?tuin=57912c43


    Java分布式互联网架构/微服务/高性能/springboot/springcloud:

    https://ke.qq.com/course/179440?tuin=57912c43

    展开全文
  • 进程线程的概念、区别进程线程间通信

    千次阅读 多人点赞 2020-08-02 16:24:25
    进程与线程的概念,以及为什么要有进程线程,其中有什么区别,他们各自又是怎么同步的? 1. 基本概念: 进程是对运行时程序的封装,是系统进行资源调度分配的的基本单位,实现了操作系统的并发; 线程是进程的子...

    进程与线程的概念,以及为什么要有进程线程,其中有什么区别,他们各自又是怎么同步的?

    1. 基本概念:

    进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发

    线程是进程的子任务,是CPU调度和分派的基本单位用于保证程序的实时性,实现进程内部的并发;线程是操作系统可识别的最小执行和调度单位。每个线程都独自占用一个虚拟处理器:独自的寄存器组指令计数器和处理器状态。每个线程完成不同的任务,但是共享同一地址空间(也就是同样的动态内存,映射文件,目标代码等等),打开的文件队列和其他内核资源

    2. 区别:
    1. 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。

    2. 进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。(资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。)

    3. 进程是资源分配的最小单位,线程是CPU调度的最小单位

    4. 系统开销: 由于在创建或撤消进程时,系统都要为之分配或回收资源,如内存空间、I/o设备等。因此,操作系统所付出的开销将显著地大于在创建或撤消线程时的开销。类似地,在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销

    5. 通信:由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现,也变得比较容易。进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。在有的系统中,线程的切换、同步和通信都无须操作系统内核的干预

    6. 进程编程调试简单可靠性高,但是创建销毁开销大;线程正相反,开销小,切换速度快,但是编程调试相对复杂

    7. 进程间不会相互影响 ;线程一个线程挂掉将导致整个进程挂掉

    8. 进程适应于多核、多机分布;线程适用于多核

    进程间通信的方式:

    进程间通信主要包括管道、系统IPC(包括消息队列、信号量、信号、共享内存等)、以及套接字socket

    1.管道:

    管道主要包括匿名管道和命名管道:管道可用于具有亲缘关系的父子进程间的通信,命名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信

    • 1.1 匿名管道PIPE
    1. 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端
    2. 只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)
    3. 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
    • 1.2 命名管道FIFO:
    1. FIFO可以在无关的进程之间交换数据
    2. FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中
    2. 系统IPC:
    • 2.1 消息队列
      消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标记。 (消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点)具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息;

    特点:

    1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
    2. 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
    3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
    • 2.2 信号量semaphore
      信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器,可以用来控制多个进程对共享资源的访问。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

    特点:

    1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
    2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
    3. 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数
    4. 支持信号量组
    2.3 信号signal

    信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

    2.4 共享内存(Shared Memory)

    它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等

    特点:

    1. 共享内存是最快的一种IPC,因为进程是直接对内存进行存取
    2. 因为多个进程可以同时操作,所以需要进行同步
    3. 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问
    3.套接字SOCKET:

    socket也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同主机之间的进程通信。

    • 线程间通信的方式:
      临界区:通过多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问;
      互斥量Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问
      信号量Semphare:为控制具有有限数量的用户资源而设计的,它允许多个线程在同一时刻去访问同一个资源,但一般需要限制同一时刻访问此资源的最大线程数目。
      事件(信号),Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作进程间通信的方式:
      进程间通信主要包括管道、系统IPC(包括消息队列、信号量、信号、共享内存等)、以及套接字socket。
    展开全文
  • 进程和线程的深入理解

    万次阅读 多人点赞 2019-04-25 00:14:40
    进程和线程的深入理解精确概括进程和线程区别 既然要谈区别,那么首先需要理解什么是进程和线程。 之前,我读到一篇材料,发现有一个很好的类比,可以把它们解释地清晰易懂。 1.计算机的核心是CPU,它承担了所有的...

    进程和线程的深入理解


    下面是抽象类比:

    单CPU:一台单核处理器计算机 = 一个车间;
    多CPU:一台多核处理器计算机 = 一座工厂;

    进程:一个车间 = 一个进程; (即一个运行的程序)
    多进程:一座工厂可以同时运行多个车间;
    CPU和进程单CPU只能同时运行单个进程,多CPU可以同时运行多个进程

    线程:车间内一个工人 = 一个线程;
    进程与线程一个进程可以包括多个线程

    线程间内存共享:车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。
    一个进程的内存空间是共享的,每个线程都可以使用这些共享内存

    内存安全:可是,每个车间容纳大小不同,有的最多只能容纳一个人。车间人满的时候,其他人就进不去了。
    一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

    互斥锁:一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。
    这就叫"互斥锁"–Mutex,防止两个线程同时读写某一块内存区域

    信号量:这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。
    这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突

    锁和信号量:不难看出,互斥锁是信号量的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

    操作系统的资源分配与调度逻辑

    • 以多进程形式,允许多个任务同时运行;
    • 以多线程形式,允许单个任务分成不同的部分运行;
    • 提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

    下面是严谨的解释:

    进程

    进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。

    线程

    线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

    进程和线程的关系

    线程是进程的一部分
    一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

    进程和线程的区别

    理解它们的差别,我从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)

    根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

    开销方面:每个进程都有独立的代码和数据空间(程序上下文),进程之间切换开销大;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小

    所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

    内存分配:系统为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源

    包含关系:线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程

    展开全文
  • 进程与多线程区别

    万次阅读 多人点赞 2016-04-21 10:01:16
    在Unix上编程采用多线程还是多进程的争执由来已久,这种争执最常见到在C/S通讯中服务端并发技术 的选型上,比如WEB服务器技术中,Apache是采用多进程的(perfork模式,每客户连接对应一个进程,每进程中只存在唯一一...

    在Unix上编程采用多线程还是多进程的争执由来已久,这种争执最常见到在C/S通讯中服务端并发技术 的选型上,比如WEB服务器技术中,Apache是采用多进程的(perfork模式,每客户连接对应一个进程,每进程中只存在唯一一个执行线程), Java的Web容器Tomcat、Websphere等都是多线程的(每客户连接对应一个线程,所有线程都在一个进程中)。

    从Unix发展历史看,伴随着Unix的诞生进程就出现了,而线程很晚才被系统支持,例如Linux直到内核2.6,才支持符合Posix规范的NPTL线程库。进程和线程的特点,也就是各自的优缺点如下:

    进程优点:编程、调试简单,可靠性较高。
    进程缺点:创建、销毁、切换速度慢,内存、资源占用大。
    线程优点:创建、销毁、切换速度快,内存、资源占用小。
    线程缺点:编程、调试复杂,可靠性较差。

    上面的对比可以归结为一句话:“线程快而进程可靠性高”。线程有个别名叫“轻量级进程”,在有的书籍资料上介绍线程可以十倍、百倍的效率快于进程; 而进程之间不共享数据,没有锁问题,结构简单,一个进程崩溃不像线程那样影响全局,因此比较可靠。我相信这个观点可以被大部分人所接受,因为和我们所接受 的知识概念是相符的。

    在写这篇文章前,我也属于这“大部分人”,这两年在用C语言编写的几个C/S通讯程序中,因时间紧总是采用多进程并发技术,而且是比较简单的现场为 每客户fork()一个进程,当时总是担心并发量增大时负荷能否承受,盘算着等时间充裕了将它改为多线程形式,或者改为预先创建进程的形式,直到最近在网 上看到了一篇论文《Linux系统下多线程与多进程性能分析》作者“周丽 焦程波 兰巨龙”,才认真思考这个问题,我自己也做了实验,结论和论文作者的相似,但对大部分人可以说是颠覆性的。

    下面是得出结论的实验步骤和过程,结论究竟是怎样的? 感兴趣就一起看看吧。

     

    实验代码使用周丽论文中的代码样例,我做了少量修改,值得注意的是这样的区别:

    论文实验和我的实验时间不同,论文所处的年代linux内核是2.4,我的实验linux内核是2.6,2.6使用的线程库是NPTL,2.4使用的是老的Linux线程库(用进程模拟线程的那个LinuxThread)。

    论文实验和我用的机器不同,论文描述了使用的环境:单 cpu 机器基本配置为:celeron 2.0 GZ, 256M, Linux 9.2,内核 2.4.8。我的环境是我的工作本本:单cpu单核celeron(R) M 1.5 GZ,1.5G内存,ubuntu10.04 desktop,内核2.6.32。

    进程实验代码(fork.c):

    1. #include <stdlib.h>
    2. #include <stdio.h>
    3. #include <signal.h>
    4.  
    5. #define P_NUMBER 255    /* 并发进程数量 */
    6. #define COUNT 100       /* 每进程打印字符串次数 */
    7. #define TEST_LOGFILE "logFile.log"
    8. FILE *logFile = NULL;
    9.  
    10. char *s = "hello linux\0";
    11.  
    12. int main()
    13. {
    14.     int i = 0,j = 0;
    15.     logFile = fopen(TEST_LOGFILE, "a+")/* 打开日志文件 */
    16.     for(i = 0; i < P_NUMBER; i++)
    17.     {
    18.         if(fork() == 0) /* 创建子进程,if(fork() == 0){}这段代码是子进程运行区间 */
    19.         {
    20.             for(j = 0;j < COUNT; j++)
    21.             {
    22.                 printf("[%d]%s\n", j, s)/* 向控制台输出 */
    23.                 fprintf(logFile,"[%d]%s\n", j, s)/* 向日志文件输出 */
    24.             }
    25.             exit(0)/* 子进程结束 */
    26.         }
    27.     }
    28.  
    29.     for(i = 0; i < P_NUMBER; i++) /* 回收子进程 */
    30.     {
    31.         wait(0);
    32.     }
    33.  
    34.     printf("OK\n");
    35.     return 0;
    36. }

    进程实验代码(thread.c):

    1. #include <pthread.h>
    2. #include <unistd.h>
    3. #include <stdlib.h>
    4. #include <stdio.h>
    5.  
    6. #define P_NUMBER 255    /* 并发线程数量 */
    7. #define COUNT 100       /* 每线程打印字符串次数 */
    8. #define Test_Log "logFIle.log"
    9. FILE *logFile = NULL;
    10.  
    11. char *s = "hello linux\0";
    12.  
    13. print_hello_linux() /* 线程执行的函数 */
    14. {
    15.     int i = 0;
    16.     for(i = 0; i < COUNT; i++)
    17.     {
    18.         printf("[%d]%s\n", i, s)/* 向控制台输出 */
    19.         fprintf(logFile, "[%d]%s\n", i, s)/* 向日志文件输出 */
    20.     }
    21.     pthread_exit(0)/* 线程结束 */
    22. }
    23.  
    24. int main()
    25. {
    26.     int i = 0;
    27.     pthread_t pid[P_NUMBER]/* 线程数组 */
    28.     logFile = fopen(Test_Log, "a+")/* 打开日志文件 */
    29.  
    30.     for(i = 0; i < P_NUMBER; i++)
    31.         pthread_create(&pid[i]NULL(void *)print_hello_linux, NULL)/* 创建线程 */
    32.  
    33.     for(i = 0; i < P_NUMBER; i++)
    34.         pthread_join(pid[i],NULL)/* 回收线程 */
    35.  
    36.     printf("OK\n");
    37.     return 0;
    38. }

    两段程序做的事情是一样的,都是创建“若干”个进程/线程,每个创建出的进程/线程打印“若干”条“hello linux”字符串到控制台和日志文件,两个“若干”由两个宏 P_NUMBER和COUNT分别定义,程序编译指令如下:

    diaoyf@ali:~/tmp1$ gcc -o fork fork.c
    diaoyf@ali:~/tmp1$ gcc -lpthread -o thread thread.c

    实验通过time指令执行两个程序,抄录time输出的挂钟时间(real时间):

    time ./fork
    time ./thread

    每批次的实验通过改动宏 P_NUMBER和COUNT来调整进程/线程数量和打印次数,每批次测试五轮,得到的结果如下:

    一、重复周丽论文实验步骤

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m1.277s 0m1.175s 0m1.227s 0m1.245s 0m1.228s 0m1.230s
    多线程 0m1.150s 0m1.192s 0m1.095s 0m1.128s 0m1.177s 0m1.148s

    进程线程数:255 / 打印次数:100

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m6.341s 0m6.121s 0m5.966s 0m6.005s 0m6.143s 0m6.115s
    多线程 0m6.082s 0m6.144s 0m6.026s 0m5.979s 0m6.012s 0m6.048s

    进程线程数:255 / 打印次数:500

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m12.155s 0m12.057s 0m12.433s 0m12.327s 0m11.986s 0m12.184s
    多线程 0m12.241s 0m11.956s 0m11.829s 0m12.103s 0m11.928s 0m12.011s

    进程线程数:255 / 打印次数:1000

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 1m2.182s 1m2.635s 1m2.683s 1m2.751s 1m2.694s 1m2.589s
    多线程 1m2.622s 1m2.384s 1m2.442s 1m2.458s 1m3.263s 1m2.614s

    进程线程数:255 / 打印次数:5000

    本轮实验是为了和周丽论文作对比,因此将进程/线程数量限制在255个,论文也是测试了255个进程/线程分别进行10 次,50 次,100 次,200 次……900 次打印的用时,论文得出的结果是:任务量较大时,多进程比多线程效率高;而完成的任务量较小时,多线程比多进程要快,重复打印 600 次时,多进程与多线程所耗费的时间相同。

    虽然我的实验直到5000打印次数时,多进程才开始领先,但考虑到使用的是NPTL线程库的缘故,从而可以证实了论文的观点。从我的实验数据看,多线程和多进程两组数据非常接近,考虑到数据的提取具有瞬间性,因此可以认为他们的速度是相同的。

    当前的网络环境中,我们更看中高并发、高负荷下的性能,纵观前面的实验步骤,最长的实验周期不过1分钟多一点,因此下面的实验将向两个方向延伸,第一,增加并发数量,第二,增加每进程/线程的工作强度。

    二、增加并发数量的实验

    下面的实验打印次数不变,而进程/线程数量逐渐增加。在实验过程中多线程程序在后三组(线程数500,800,1000)的测试中都出现了“段错误”,出现错误的原因和线程栈的大小有关。

    实验中的计算机CPU是32位的赛扬,寻址最大范围是4GB(2的32次方),Linux是按照3GB/1GB的方式来分配内存,其中1GB属于所 有进程共享的内核空间,3GB属于用户空间(进程虚拟内存空间),对于进程而言只有一个栈,这个栈可以用尽这3GB空间(计算时需要排除程序文本、数据、 共享库等占用的空间),所以它的大小通常不是问题。但对线程而言每个线程有一个线程栈,这3GB空间会被所有线程栈摊分,线程数量太多时,线程栈累计的大 小将超过进程虚拟内存空间大小,这就是实验中出现的“段错误”的原因。

    Linux2.6的默认线程栈大小是8M,可以通过 ulimit -s 命令查看或修改,我们可以计算出线程数的最大上线: (1024*1024*1024*3) / (1024*1024*8) = 384,实际数字应该略小与384,因为还要计算程序文本、数据、共享库等占用的空间。在当今的稍显繁忙的WEB服务器上,突破384的并发访问并不是稀 罕的事情,要继续下面的实验需要将默认线程栈的大小减小,但这样做有一定的风险,比如线程中的函数分配了大量的自动变量或者函数涉及很深的栈帧(典型的是 递归调用),线程栈就可能不够用了。可以配合使用POSIX.1规定的两个线程属性guardsize和stackaddr来解决线程栈溢出问题, guardsize控制着线程栈末尾之后的一篇内存区域,一旦线程栈在使用中溢出并到达了这片内存,程序可以捕获系统内核发出的告警信号,然后使用 malloc获取另外的内存,并通过stackaddr改变线程栈的位置,以获得额外的栈空间,这个动态扩展栈空间办法需要手工编程,而且非常麻烦。

    有两种方法可以改变线程栈的大小,使用 ulimit -s 命令改变系统默认线程栈的大小,或者在代码中创建线程时通过pthread_attr_setstacksize函数改变栈尺寸,在实验中使用的是第一 种,在程序运行前先执行ulimit指令将默认线程栈大小改为1M:

    diaoyf@ali:~/tmp1$ ulimit -s 1024
    diaoyf@ali:~/tmp1$ time ./thread

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m4.958s 0m5.032s 0m5.181s 0m4.951s 0m5.032s 0m5.031s
    多线程 0m4.994s 0m5.040s 0m5.071s 0m5.113s 0m5.079s 0m5.059s

    进程线程数:100 / 打印次数:1000

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m12.155s 0m12.057s 0m12.433s 0m12.327s 0m11.986s 0m12.184s
    多线程 0m12.241s 0m11.956s 0m11.829s 0m12.103s 0m11.928s 0m12.011s

    进程线程数:255 / 打印次数:1000 (这里使用了第一次的实验数据)

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m17.686s 0m17.569s 0m17.609s 0m17.663s 0m17.784s 0m17.662s
    多线程 0m17.694s 0m17.976s 0m17.884s 0m17.785s 0m18.261s 0m17.920s

    进程线程数:350 / 打印次数:1000

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m23.638s 0m23.543s 0m24.135s 0m23.981s 0m23.507s 0m23.761s
    多线程 0m23.634s 0m23.326s 0m23.408s 0m23.294s 0m23.980s 0m23.528s

    进程线程数:500 / 打印次数:1000 (线程栈大小更改为1M)

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m38.517s 0m38.133s 0m38.872s 0m37.971s 0m38.005s 0m38.230s
    多线程 0m38.011s 0m38.049s 0m37.635s 0m38.219s 0m37.861s 0m37.995s

    进程线程数:800 / 打印次数:1000 (线程栈大小更改为1M)

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m48.157s 0m47.921s 0m48.124s 0m48.081s 0m48.126s 0m48.082s
    多线程 0m47.513s 0m47.914s 0m48.073s 0m47.920s 0m48.652s 0m48.014s

    进程线程数:1000 / 打印次数:1000 (线程栈大小更改为1M)

    出现了线程栈的问题,让我特别关心Java线程是怎样处理的,因此用Java语言写了同样的实验程序,Java程序加载虚拟机环境比较耗时,所以没 有用time提取测试时间,而直接将测时写入代码。对Linux上的C编程不熟悉的Java程序员也可以用这个程序去对比理解上面的C语言试验程序。

    1. import java.io.File;
    2. import java.io.FileNotFoundException;
    3. import java.io.FileOutputStream;
    4. import java.io.IOException;
    5.  
    6. public class MyThread extends Thread
    7. {
    8.     static int P_NUMBER = 1000;     /* 并发线程数量 */
    9.     static int COUNT = 1000;        /* 每线程打印字符串次数 */
    10.  
    11.     static String s = "hello linux\n";
    12.        
    13.     static FileOutputStream out = null/* 文件输出流 */
    14.     @Override
    15.     public void run()
    16.     {
    17.         for (int i = 0; i < COUNT; i++)
    18.         {
    19.             System.out.printf("[%d]%s", i, s)/* 向控制台输出 */
    20.            
    21.             StringBuilder sb = new StringBuilder(16);
    22.             sb.append("[").append(i).append("]").append(s);
    23.             try
    24.             {
    25.                 out.write(sb.toString().getBytes());/* 向日志文件输出 */
    26.             }
    27.             catch (IOException e)
    28.             {
    29.                 e.printStackTrace();
    30.             }
    31.         }
    32.     }
    33.  
    34.     public static void main(String[] args) throws FileNotFoundExceptionInterruptedException
    35.     {
    36.         MyThread[] threads = new MyThread[P_NUMBER]/* 线程数组 */
    37.        
    38.         File file = new File("Javalogfile.log");
    39.         out = new FileOutputStream(file, true);  /* 日志文件输出流 */
    40.        
    41.         System.out.println("开始运行");
    42.         long start = System.currentTimeMillis();
    43.  
    44.         for (int i = 0; i < P_NUMBER; i++) //创建线程
    45.         {
    46.             threads[i] = new MyThread();
    47.             threads[i].start();
    48.         }
    49.  
    50.         for (int i = 0; i < P_NUMBER; i++) //回收线程
    51.         {
    52.             threads[i].join();
    53.         }
    54.        
    55.         System.out.println("用时:" + (System.currentTimeMillis() – start) + " 毫秒");
    56.         return;
    57.     }
    58.  
    59. }
      第1次 第2次 第3次 第4次 第5次 平均
    Java 65664 毫秒 66269 毫秒 65546 毫秒 65931 毫秒 66540 毫秒 65990 毫秒

    线程数:1000 / 打印次数:1000

    Java程序比C程序慢一些在情理之中,但Java程序并没有出现线程栈问题,5次测试都平稳完成,可以用下面的ps指令获得java进程中线程的数量:

    diaoyf@ali:~$ ps -eLf | grep MyThread | wc -l
    1010

    用ps测试线程数在1010上维持了很长时间,多出的10个线程应该是jvm内部的管理线程,比如用于GC。我不知道Java创建线程时默认栈的大 小是多少,很多资料说法不统一,于是下载了Java的源码jdk-6u21-fcs-src-b07-jrl-17_jul_2010.jar(实验环境 安装的是 SUN jdk 1.6.0_20-b02),但没能从中找到需要的信息。对于jvm的运行,java提供了控制参数,因此再次测试时,通过下面的参数将Java线程栈大 小定义在8192k,和Linux的默认大小一致:

    diaoyf@ali:~/tmp1$ java -Xss8192k MyThread

    出乎意料的是并没有出现想象中的异常,但用ps侦测线程数最高到达337,我判断程序在创建线程时在栈到达可用内存的上线时就停止继续创建了,程序 运行的时间远小于估计值也证明了这个判断。程序虽然没有抛出异常,但运行的并不正常,另一个问题是最后并没有打印出“用时 xxx毫秒”信息。

    这次测试更加深了我的一个长期的猜测:Java的Web容器不稳定。因为我是多年编写B/S的Java程序员,WEB服务不稳定常常挂掉也是司空见 惯的,除了自己或项目组成员水平不高,代码编写太烂的原因之外,我一直猜测还有更深层的原因,如果就是线程原因的话,这颠覆性可比本篇文章的多进程性能颠 覆性要大得多,想想世界上有多少Tomcat、Jboss、Websphere、weblogic在跑着,嘿嘿。

    这次测试还打破了以前的一个说法:单CPU上并发超过6、7百,线程或进程间的切换就会占用大量CPU时间,造成服务器效率会急剧下降。但从上面的实验来看,进程/线程数到1000时(这差不多是非常繁忙的WEB服务器了),仍具有很好的线性。

    三、增加每进程/线程的工作强度的实验

    这次将程序打印数据增大,原来打印字符串为:

    1. char *s = "hello linux\0";

    现在修改为每次打印256个字节数据:

    1. char *s = "1234567890abcdef\
    2. 1234567890abcdef\
    3. 1234567890abcdef\
    4. 1234567890abcdef\
    5. 1234567890abcdef\
    6. 1234567890abcdef\
    7. 1234567890abcdef\
    8. 1234567890abcdef\
    9. 1234567890abcdef\
    10. 1234567890abcdef\
    11. 1234567890abcdef\
    12. 1234567890abcdef\
    13. 1234567890abcdef\
    14. 1234567890abcdef\
    15. 1234567890abcdef\
    16. 1234567890abcdef\0";
      第1次 第2次 第3次 第4次 第5次 平均
    多进程 0m28.149s 0m27.993s 0m28.094s 0m27.657s 0m28.016s 0m27.982s
    多线程 0m28.171s 0m27.764s 0m27.865s 0m28.041s 0m27.780s 0m27.924s

    进程线程数:255 / 打印次数:100

      第1次 第2次 第3次 第4次 第5次 平均
    多进程 2m20.357s 2m19.740s 2m19.965s 2m19.788s 2m19.796s 2m19.929s
    多线程 2m20.061s 2m20.462s 2m19.789s 2m19.514s 2m19.479s 2m19.861s

    进程线程数:255 / 打印次数:500

      第1次 第2次
    多进程 9m39s 9m17s
    多线程 9m31s 9m22s

    进程线程数:255 / 打印次数:2000 (实验太耗时,因此只进行了2轮比对)

    【实验结论】

    从上面的实验比对结果看,即使Linux2.6使用了新的NPTL线程库(据说比原线程库性能提高了很多,唉,又是据说!),多线程比较多进程在效率上没有任何的优势,在线程数增大时多线程程序还出现了运行错误,实验可以得出下面的结论:

    在Linux2.6上,多线程并不比多进程速度快,考虑到线程栈的问题,多进程在并发上有优势。

    四、多进程和多线程在创建和销毁上的效率比较

    预先创建进程或线程可以节省进程或线程的创建、销毁时间,在实际的应用中很多程序使用了这样的策略,比如Apapche预先创建进程、Tomcat 预先创建线程,通常叫做进程池或线程池。在大部分人的概念中,进程或线程的创建、销毁是比较耗时的,在stevesn的著作《Unix网络编程》中有这样 的对比图(第一卷 第三版 30章 客户/服务器程序设计范式):

    行号 服务器描述 进程控制CPU时间(秒,与基准之差)
    Solaris2.5.1 Digital Unix4.0b BSD/OS3.0
    0 迭代服务器(基准测试,无进程控制) 0.0 0.0 0.0
    1 简单并发服务,为每个客户请求fork一个进程 504.2 168.9 29.6
    2 预先派生子进程,每个子进程调用accept   6.2 1.8
    3 预先派生子进程,用文件锁保护accept 25.2 10.0 2.7
    4 预先派生子进程,用线程互斥锁保护accept 21.5    
    5 预先派生子进程,由父进程向子进程传递套接字 36.7 10.9 6.1
    6 并发服务,为每个客户请求创建一个线程 18.7 4.7  
    7 预先创建线程,用互斥锁保护accept 8.6 3.5  
    8 预先创建线程,由主线程调用accept 14.5 5.0  

    stevens已驾鹤西去多年,但《Unix网络编程》一书仍具有巨大的影响力,上表中stevens比较了三种服务器上多进程和多线程的执行效 率,因为三种服务器所用计算机不同,表中数据只能纵向比较,而横向无可比性,stevens在书中提供了这些测试程序的源码(也可以在网上下载)。书中介 绍了测试环境,两台与服务器处于同一子网的客户机,每个客户并发5个进程(服务器同一时间最多10个连接),每个客户请求从服务器获取4000字节数据, 预先派生子进程或线程的数量是15个。

    第0行是迭代模式的基准测试程序,服务器程序只有一个进程在运行(同一时间只能处理一个客户请求),因为没有进程或线程的调度切换,因此它的速度是 最快的,表中其他服务模式的运行数值是比迭代模式多出的差值。迭代模式很少用到,在现有的互联网服务中,DNS、NTP服务有它的影子。第1~5行是多进 程服务模式,期中第1行使用现场fork子进程,2~5行都是预先创建15个子进程模式,在多进程程序中套接字传递不太容易(相对于多线程), stevens在这里提供了4个不同的处理accept的方法。6~8行是多线程服务模式,第6行是现场为客户请求创建子线程,7~8行是预先创建15个 线程。表中有的格子是空白的,是因为这个系统不支持此种模式,比如当年的BSD不支持线程,因此BSD上多线程的数据都是空白的。

    从数据的比对看,现场为每客户fork一个进程的方式是最慢的,差不多有20倍的速度差异,Solaris上的现场fork和预先创建子进程的最大差别是504.2 :21.5,但我们不能理解为预先创建模式比现场fork快20倍,原因有两个:

    1. stevens的测试已是十几年前的了,现在的OS和CPU已起了翻天覆地的变化,表中的数值需要重新测试。

    2. stevens没有提供服务器程序整体的运行计时,我们无法理解504.2 :21.5的实际运行效率,有可能是1504.2 : 1021.5,也可能是100503.2 : 100021.5,20倍的差异可能很大,也可能可以忽略。

    因此我写了下面的实验程序,来计算在Linux2.6上创建、销毁10万个进程/线程的绝对用时。

    创建10万个进程(forkcreat.c):

    1. #include <stdlib.h>
    2. #include <signal.h>
    3. #include <stdio.h>
    4. #include <unistd.h>
    5. #include <sys/stat.h>
    6. #include <fcntl.h>
    7. #include <sys/types.h>
    8. #include <sys/wait.h>
    9.  
    10. int count;  /* 子进程创建成功数量 */
    11. int fcount; /* 子进程创建失败数量 */
    12. int scount; /* 子进程回收数量 */
    13.  
    14. /* 信号处理函数–子进程关闭收集 */
    15. void sig_chld(int signo)
    16. {
    17.    
    18.     pid_t chldpid; /* 子进程id */
    19.     int stat; /* 子进程的终止状态 */
    20.  
    21.     /* 子进程回收,避免出现僵尸进程 */
    22.     while ((chldpid = wait(&stat)) > 0)
    23.     {
    24.         scount++;
    25.     }
    26. }
    27.  
    28. int main()
    29. {
    30.     /* 注册子进程回收信号处理函数 */
    31.     signal(SIGCHLD, sig_chld);
    32.  
    33.     int i;
    34.     for (i = 0; i < 100000; i++) //fork()10万个子进程
    35.     {
    36.         pid_t pid = fork();
    37.         if (pid == -1) //子进程创建失败
    38.         {
    39.             fcount++;
    40.         }
    41.         else if (pid > 0) //子进程创建成功
    42.         {
    43.             count++;
    44.         }
    45.         else if (pid == 0) //子进程执行过程
    46.         {
    47.             exit(0);
    48.         }
    49.     }
    50.  
    51.     printf("count: %d fcount: %d scount: %d\n", count, fcount, scount);
    52. }

    创建10万个线程(pthreadcreat.c):

    1. #include <stdio.h>
    2. #include <pthread.h>
    3.  
    4. int count = 0/* 成功创建线程数量 */
    5.  
    6. void thread(void)
    7. {
    8.     /* 线程啥也不做 */
    9. }
    10.  
    11. int main(void)
    12. {
    13.     pthread_t id; /* 线程id */
    14.     int i,ret;
    15.  
    16.     for (i = 0; i < 100000; i++) /* 创建10万个线程 */
    17.     {
    18.         ret = pthread_create(&id, NULL(void *)thread, NULL);
    19.         if(ret != 0)
    20.         {
    21.             printf ("Create pthread error!\n");
    22.             return (1);
    23.         }
    24.  
    25.         count++;
    26.  
    27.         pthread_join(id, NULL);
    28.     }
    29.    
    30.     printf("count: %d\n", count);
    31.  
    32. }

    创建10万个线程的Java程序:

    1. public class ThreadTest
    2. {
    3.     public static void main(String[] ags) throws InterruptedException
    4.     {
    5.         System.out.println("开始运行");
    6.         long start = System.currentTimeMillis();
    7.         for(int i = 0; i < 100000; i++) //创建10万个线程
    8.         {
    9.             Thread athread = new Thread();  //创建线程对象
    10.             athread.start();                //启动线程
    11.             athread.join();                 //等待该线程停止
    12.         }
    13.        
    14.         System.out.println("用时:" + (System.currentTimeMillis() – start) + " 毫秒");
    15.     }
    16. }

    在我的赛扬1.5G的CPU上测试结果如下(仍采用测试5次后计算平均值):

    创建销毁10万个进程 创建销毁10万个线程 创建销毁10万个线程(Java)
    0m18.201s 0m3.159s 12286毫秒

    从数据可以看出,多线程比多进程在效率上有5~6倍的优势,但不能让我们在使用那种并发模式上定性,这让我想起多年前政治课上的一个场景:在讲到优 越性时,面对着几个对此发表质疑评论的调皮男生,我们的政治老师发表了高见,“不能只横向地和当今的发达国家比,你应该纵向地和过去中国几十年的发展历史 比”。政治老师的话套用在当前简直就是真理,我们看看,即使是在赛扬CPU上,创建、销毁进程/线程的速度都是空前的,可以说是有质的飞跃的,平均创建销 毁一个进程的速度是0.18毫秒,对于当前服务器几百、几千的并发量,还有预先派生子进程/线程的必要吗?

    预先派生子进程/线程比现场创建子进程/线程要复杂很多,不仅要对池中进程/线程数量进行动态管理,还要解决多进程/多线程对accept的“抢” 问题,在stevens的测试程序中,使用了“惊群”和“锁”技术。即使stevens的数据表格中,预先派生线程也不见得比现场创建线程快,在 《Unix网络编程》第三版中,新作者参照stevens的测试也提供了一组数据,在这组数据中,现场创建线程模式比预先派生线程模式已有了效率上的优 势。因此我对这一节实验下的结论是:

    预先派生进程/线程的模式(进程池、线程池)技术,不仅复杂,在效率上也无优势,在新的应用中可以放心大胆地为客户连接请求去现场创建进程和线程。

    我想,这是fork迷们最愿意看到的结论了。

    五、并发服务的不可测性

    看到这里,你会感觉到我有挺进程、贬线程的论调,实际上对于现实中的并发服务具有不可测性,前面的实验和结论只可做参考,而不可定性。对于不可测性,我举个生活中的例子。

    这几年在大都市生活的朋友都感觉城市交通状况越来越差,到处堵车,从好的方面想这不正反应了我国GDP的高速发展。如果你7、8年前来到西安市,穿 过南二环上的一些十字路口时,会发现一个奇怪的U型弯的交通管制,为了更好的说明,我画了两张图来说明,第一张图是采用U型弯之前的,第二张是采用U型弯 之后的。

     

    南二环交通图一

     

    南二环交通图二

    为了讲述的方便,我们不考虑十字路口左拐的情况,在图一中东西向和南北向的车辆交汇在十字路口,用红绿灯控制同一时间只能东西向或南北向通行,一般 的十字路口都是这样管控的。随着车辆的增多,十字路口的堵塞越来越严重,尤其是上下班时间经常出现堵死现象。于是交通部门在不动用过多经费的情况下而采用 了图二的交通管制,东西向车辆行进方式不变,而南北向车辆不能直行,需要右拐到下一个路口拐一个超大的U型弯,这样的措施避免了因车辆交错而引发堵死的次 数,从而提高了车辆的通过效率。我曾经问一个每天上下班乘公交经过此路口的同事,他说这样的改动不一定每次上下班时间都能缩短,但上班时间有保障了,从而 迟到次数减少了。如果今天你去西安市的南二环已经见不到U型弯了,东西向建设了高架桥,车辆分流后下层的十字路口已恢复为图一方式。

    从效率的角度分析,在图一中等一个红灯45秒,远远小于图二拐那个U型弯用去的时间,但实际情况正好相反。我们可以设想一下,如果路上的所有运行车 辆都是同一型号(比如说全是QQ3微型车),所有的司机都遵守交规,具有同样的心情和性格,那么图一的通行效率肯定比图二高。现实中就不一样了,首先车辆 不统一,有大车、小车、快车、慢车,其次司机的品行不一,有特别遵守交规的,有想耍点小聪明的,有性子慢的,也有的性子急,时不时还有三轮摩托逆行一下, 十字路口的“死锁”也就难免了。

    那么在什么情况下图二优于图一,是否能拿出一个科学分析数据来呢?以现在的科学技术水平是拿不出来的,就像长期的天气预报不可预测一样,西安市的交管部门肯定不是分析各种车辆的运行规律、速度,再进行复杂的社会学、心理学分析做出U型弯的决定的,这就是要说的不可测性。

    现实中的程序亦然如此,比如WEB服务器,有的客户在快车道(宽带),有的在慢车道(窄带),有的性子慢(等待半分钟也无所谓),有的性子急(拼命 的进行浏览器刷新),时不时还有一两个黑客混入其中,这种情况每个服务器都不一样,既是是同一服务器每时每刻的变化也不一样,因此说不具有可测性。开发者 和维护者能做的,不论是前面的这种实验测试,还是对具体网站进行的压力测试,最多也就能模拟相当于QQ3通过十字路口的场景。

    结束语

    本篇文章比较了Linux系统上多线程和多进程的运行效率,在实际应用时还有其他因素的影响,比如网络通讯时采用长连接还是短连接,是否采用 select、poll,java中称为nio的机制,还有使用的编程语言,例如Java不能使用多进程,PHP不能使用多线程,这些都可能影响到并发模 式的选型。

    展开全文
  • Python中进程和线程区别详解

    千次阅读 2019-03-04 09:30:46
     进程进程时计算机程序一次执行的实例,由 程序段 数据段 PCB组成,是计算机资源分配调度的基本单位,也是线程的容器  线程线程也叫作轻量级进程,是程序执行的最小单位,他本身只拥有少部分执行必须的资源...
  • 进程和线程的定义及区别一, 进程的概念进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。由 于多道程序系统所带来的复杂环境,程序本身有了并行性【为了充分利用资源,在主存中同时...
  • 进程线程代码实现,本质区别

    千次阅读 2015-05-21 10:07:54
    线程 or 多进程 (转强力推荐) 在Unix上编程采用多线程还是多进程的争执由来已久,这种争执最常见到在C/S通讯中服务端并发技术 的选型上,比如WEB服务器技术中,Apache是采用多进程的(perfork模式,每客户...
  • 进程和线程区别

    万次阅读 2009-02-22 20:37:00
    线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。从逻辑角度来看,多线
  • 进程和线程区别(操作系统级别解析)

    万次阅读 多人点赞 2018-12-03 16:21:05
    关于进程和线程,大家总是说的一句话是“进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元”。这句话理论上没问题,我们来看看什么是所谓的“资源”呢。   什么是计算机资源 经典的冯诺依曼结构...
  • 线程和进程区别、linux下一些常用的指令
  • 进程和线程区别,以及应用场景

    千次阅读 多人点赞 2018-09-15 22:39:22
    什么是线程? Linux下线程进程PCB模拟...创建,销毁一个线程相较创建,销毁一个进程成本要低(创建进程要创建PCB,虚拟地址空间,创建页表,维护映射,把硬盘的代码数据加载到内存,文件描述符等等,而创建线程...
  • 程序,进程和线程区别与联系

    千次阅读 2018-05-18 03:01:21
    借鉴了各大网站,总结出的个人心得体会,转载请注明出处提到线程和进程,必须先了解一些预备知识。 程序: 程序是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的有序集合。 程序(这里前边指的是...
  • 进程和线程区别与联系

    万次阅读 2012-02-25 20:15:38
    进程(process)是指在系统中正在运行的一个应用程序,是系统资源分配的基本单位,在内存中有其完备的数据空间和代码空间,拥有完整的虚拟空间地址。...它与父进程的其它线程共享该进程所拥有的全部代码空间全局变
  • 进程线程的总结和区别

    万次阅读 2014-04-28 11:27:59
    对于进程和线程区别,很多面试或者笔试都有涉及到。我想很多朋友跟我一样,对他们都仅限于一些很粗很广的定义区分,对于很多细节一下子回答出来还是有一定难度的。下面我将对进程和线程做一个系统的总结,供大家...
  • 进程和线程区别(重点)

    千次阅读 2017-08-03 15:03:00
    简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率...
  • 进程和线程

    千次阅读 2012-10-15 10:28:54
    【描述】线程进程是一个老生常谈的话题,线程进程区别和优缺点有哪些?线程最多可以开多少个? 【解析】 1 区别  线程是CPU调度的最小单位,进程是资源分配的最小单位。进程线程的容器,真正完成代码...
  • Python 基础 之 python 中 进程线程、协程对比 区别和联系 目录 Python 基础 之 python 中 进程线程、协程对比 区别和联系 一、简单介绍 二、进程线程、协程 的定义 1. 进程 2、线程 3、协程 二、...
  • 进程线程区别和联系

    千次阅读 多人点赞 2018-08-08 21:37:00
    程序并不能单独执行,只有将程序加载到内存中,系统为他分配资源后才能够执行,这种执行的程序称之为进程,也就是说进程是系统进行资源分配调度的一个独立单位,每个进程都有自己单独的地址空间。所以说程序与进程...
  • 写给大忙人看的进程和线程

    万次阅读 多人点赞 2020-03-03 15:44:21
    我们平常说的进程和线程更多的是基于编程语言的角度来说的,那么你真的了解什么是线程和进程吗?那么我们就从操作系统的角度来了解一下什么是进程和线程进程 操作系统中最核心的概念就是 进程进程是对正在运行...
  • Python进程和线程

    千次阅读 多人点赞 2020-02-22 13:38:27
    Python进程和线程1.多任务的概念1.1 多任务的执行方式1.1.1 并发1.1.2 并行1.2 总结2. 什么是进程3. 创建进程的常用方式3.1 使用multiprocessing创建进程4. 通过队列实现进程间通信 为了实现在同一时间运行多个任务...
  • 关于Chrome的线程模型,...chrome的进程,chrome没有采用一般应用程序的单进程线程的模型,而是采用了多进程的模型,按照他的文字说明,主界面框架下的一个TAB就对应这个一个进程。但实际上,一个进程不仅仅包含一个
  • 进程线程、协程管程的区别

    千次阅读 2019-07-25 19:53:54
    操作系统的诞生是为了运行用户程序,事实上程序运行在操作系统上就变成了进程,现在就来让我们一起了解一下进程相关的内容。 进程 根据理解,我们可以对进程下个定义——进程是运行中的程序。注意,进程是一个动态的...
  • java--进程和线程

    千次阅读 多人点赞 2018-11-25 22:55:49
    进程和线程的概述 在学习线程之前要先知道什么是进程进程就是正在运行的程序,它是系统资源调度的独立单位,并且一个进程可以执行多个任务,而线程就是程序执行的任务,它是程序使用CPU的基本单位,因此也可以说...
  • 进程和线程的概念、区别与联系

    千次阅读 2014-11-13 16:03:06
    进程概念  进程是表示资源分配的基本单位,又是调度运行的基本单位。例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格、内存空间、磁盘空间、I/O设备等。然后,把该进程放人进程的...
  • ML岗位面试:上海某公司算法岗位技术(偏机器学习,证券基金行业)面试考点之进程线程区别、GD改进的算法、ROCAUC 导读:其实,考察的知识点,博主都做过,但是,emmm,这些知识点,在我写代码中,几乎不会用到...
  • 进程线程区别与联系

    千次阅读 2016-07-03 23:57:21
    线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.2.关系 一个线程可以创建撤销另一个线
  • 线程进程、多线程、多进程 多任务 小结

    千次阅读 多人点赞 2019-04-20 11:59:56
    6 线程和进程区别 7 进程的优缺点 7.1 进程的优点 7.2 进程的缺点 8 线程的优缺点 8.1 线程的优点 8.2 线程的缺点 9 多线程的优缺点 9.1 多线程的优点 9.2 多线程的缺点 10多进程的优缺点 10.1 多进程...
  • 进程和线程同步的机制以及区别

    千次阅读 2011-10-18 20:48:06
    进程和线程区别 2。它们各自同步机制  线程的: 1事件,2互斥对象,3信号量,4临界区  进程的: 3。各机制之间的不同 4。哪些属于内核?哪些不是?  事件,互斥对象,信号量属于,而临界区不是 ...
  • 如果用一句话来说明它的区别的话,那就是线程是系统执行(调度)的最小单元,进程是系统资源分配的最小单元。 进程和线程是怎么来的? 在传统的进程模型中,有两个独立的概念:资源分配与执行。所谓的执行的基本...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 240,544
精华内容 96,217
关键字:

代码说明进程和线程的区别