赞
踩
目录
线程是在进程内部运行,一个进程可以有多个线程。
打个比方,假如人是一个进程,那么走路、思考、吃饭、说话作为不同的线程。一个进程能有多个线程同时运行,就好比一个人在走路时还可以思考、说话、吃饭一样。
可以说,线程就是进程的“四肢”,是进程运行的基本单位,是CPU调度的基本单位。
画个草图如下:
总结而言,在一个程序里的一个执行路线就叫做线程,且一个进程至少要有一个执行线程。
线程与进程共享虚拟地址空间、页表等内核数据结构、数据和代码。
线程的数据结构理论上与进程的不同,但基于线程和进程的相似性,linux的线程数据结构依旧采用
task_struct结构体,与进程的一致。但是其他的操作系统线程有专属的结构,与进程的不同。也就是说,linux没有真正意义上的线程结构,而是采用进程的task_struct结构体模拟的线程。
即便线程与进程都采用task_struct结构体,但是内核数据结构依旧属于进程,线程只是与进程共享。
换句话说,进程 = 多个线程(执行流)+ 内核数据结构 + 数据 + 代码。
而task_struct本质就是进程内部的一个执行流。
对于CPU而言,本质上只是调度task_struct,而不会区分进程还是线程。
图示如下:
所有线程共享进程的内核数据结构、数据及代码,但是每个线程也有自己私有的数据。
比如线程id、寄存器和栈,还有errno、信号屏蔽字(block位图)、调度优先级。
linux的线程数据创建在共享区中,因此,线程结构在共享区中。
linux使用pthread库来创建及管理线程,而pthread作为动态库需要加载到共享区,进而线程创建在共享区中。
线程栈、局部存储数据(__pthread类型变量)及线程id由pthread库函数创建的struct pthread结构体管理。该结构体在共享区,因此,线程的栈也在共享区中。
值得注意的是:
①主线程使用虚拟地址空间中的栈区,只有其他线程使用共享区中分配的栈区。
②线程id(pthread_self()函数返回值)本质是共享区pthread库所分配给该线程空间的起始地址,即id本质是一个地址。
图示如下:
①创建线程的代价比创建进程小。创建线程只用创建task_struct结构体,而进程还有相关内核数据结构,加载数据和代码。
②线程切换效率比进程切换高。线程占用系统资源少,切换更高效。线程切换时不会清除缓存数据,进程切换会清除缓存。
③线程可以充分利用CPU多核心的优势(多线程)。可以同时执行不同的任务,使得多个任务能够并发进行。
④多线程可以提高计算密集型和IO密集型应用的效率。计算密集型应用可以将计算分给多个线程处理,IO密集型应用可以使用多线程同时进行不同的IO操作。
①多线程的健壮性差。多线程之间没有数据保护,可能存在因为线程执行顺序问题导致的数据错误。
②缺乏访问控制。线程访问某些系统函数可能会对整个进程造成影响。
③多线程程序调试难度大。多线程代码的调试比单线程困难许多。
①一个进程可以有多个线程,且只少有一个线程。
②进程拥有内核数据结构、数据及代码,线程只有使用权和必不可少的私有数据如寄存器和栈。
③线程执行效率通常更高,但不安全。
④一个线程异常,整个进程异常。
如有错误,敬请斧正
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。