网站开发面试内容,东莞网络推广外包托管,网站首页模板图片,不用编程做APP和响应式网站知识引入初识线程1.什么叫做进程#xff1f;2.什么叫做线程#xff1f;3.如何看待我们之前学习的进程#xff1f; 理解线程创建线程函数调用1.线程一旦被创建#xff0c;几乎所有资源都是被线程所共享的2.与进程之间切换相比#xff0c;线程的切换 初识线程总结#xff1… 知识引入初识线程1.什么叫做进程2.什么叫做线程3.如何看待我们之前学习的进程 理解线程创建线程函数调用1.线程一旦被创建几乎所有资源都是被线程所共享的2.与进程之间切换相比线程的切换 初识线程总结线程的优点线程的缺点线程异常线程用途Linux进程VS线程 知识引入
如何看待地址空间和页表:
地址空间是进程能看到的资源窗口页表决定进程真正拥有资源的情况页表映射多少才是拥有多少合理的对地址空间页表进行资源划分我们就可以对一个进程所有的资源进行分类
虚拟地址如何找到物理地址 最后一级页表存放的是页框的起始物理地址然后通过虚拟地址后12位为页内偏移量→物理地址 初识线程
1.什么叫做进程 进程组成PCB 地址空间 页表 物理内存映射的一部分
2.什么叫做线程
线程进程内的一个执行流
虚拟内存里面决定了进程能够看到的“资源”我们将我们的代码分成一块一块的区域我们不再像以前那样创建进程就将原进程的虚拟地址空间、页表再复制一份而是只创建PCB指向父进程指向的位置 我们首先要知道一个进程所对应的资源是可以通过虚拟地址空间和页表将部分资源划分给不同的PCB中的因为我们可以通过虚拟地址空间页表方式对进程进行资源划分单个“进程”执行力度一定要比之前的进程要细
思考: 如果OS真的要专门设计“线程”概念OS要不要管理这个线程呢? 肯定是需要的方法还是先描述在组织。在windows中为线程设计专门的数据结构表示线程对象TCB而在Linux中单纯从线程调度角度线程和进程有很多的地方是重叠的所以我们的Linux工程师不想给Linux线程专门设计对应的数据结构而是直接复用PCB 用PCB用来表示Linux内部的线程。而对于CPU来说它并不关心你的PCB是表示进程还是线程它只关心task_struct(PCB) 线程在进程内部运行线程在进程的地址空间内运行拥有该进程的一部分资源! 3.如何看待我们之前学习的进程 进程一堆的PCB 地址空间 页表 对应的物理地址
之前的进程承担系统资源的基本实体只不过内部只有一个执行流一个进程内部可以有多个执行流
站在CPU的角度看待task_struct以前进程—现在进程内的一个分支 CPU很笨它不会区分它只需要拿来就能用就行。 Linux下统称task_struct轻量级进程 小总结
Linux内核中有没有真正意义的线程呢?没有。Linux是用进程PCB来模拟线程的是一种完全属于自己的一套线程方案站在CPU的视角每一个PCB都可以称之为叫做轻量级进程Linux线程是CPU调度的基本单位而进程是承担分配系统资源的基本单位进程用来整体申请资源线程用来伸手向进程要资源。比如公司、小组、组员关系小组向公司申请资金组员向小组长拿钱Linux中没有真正意义的线程好处是什么?简单维护成本大大降低–可靠高效! 我们使用PCB来模拟线程那么我们曾经给PCB创建的一整套的数据结构与算法都可以复用。而且线程与进程有很多地方是重叠的这也给我们重新创建线程方法的编码难度大大提高更为复杂的代码带来的就是维护成本的增高 OS只认线程用户(程序员)也只认线程 Linux无法直接提供创建线程的系统调用接口而只能给我提供创建轻量级进程的接口 理解线程
我们将 家庭比作进程 家庭成员比作线程 (家庭成员)你的爸爸妈妈努力工作是为了生活更美好你的爷爷奶奶每天锻炼跳广场舞是为了身体健康你每天努力学习是为了未来有更好的生活(家庭)所有人的目的都是为了这个家更美好。家庭与家庭成员关系类比也就是进程与线程的关系 创建线程函数调用 函数原型具体可看下一章 线程控制
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);创建线程参考
#include iostream
#include cstdio
#include cassert
#include pthread.h
#include unistd.h
using namespace std;
// 新线程
void *thread_routine(void *args)
{while (true){cout 我是新线程, 我正在运行! endl;sleep(1);}
}int main()
{// typedef unsigned long int pthread_t;pthread_t tid;int n pthread_create(tid, nullptr, thread_routine, (void *)thread one);assert(0 n);(void)n;while (true){// 地址 - ?cout 我是主线程, 我正在运行! endl;sleep(1);}return 0;
}直接运行的结果 错误对“pthread create”的未定义引用 原因这个函数并不是OS提供给我们的系统调用Linux没有真正意义上的线程只有轻量级进程所以Linux只能提供轻量级进程的接口无法给我们直接创建线程。而这个函数是第三方库提供给我们的不是语言提供的也不是OS提供的这个库是
Compile and link with -pthread.当然这个库大概率是在系统之中已经有的为了使用这个第三方库我们编译时需要找到这个库 -lpthread
g -o mythread mythread.cc -lpthread -stdc11代码执行结果 很明显有两个执行流在一起运行但是 如何看到这两个执行流信息呢
ps -aLLWPlight weight process 轻量级进程ID 两个线程的PID都是相同的主线程是PID与LWP相同的那个
CPU调度的时候是以哪一个id为标识符表示特定一个执行流的呢 LWP 当我们只有一个执行流的时候PID与LWP是相同的在这种情况下使用PID标识或LWP标识都可以 1.线程一旦被创建几乎所有资源都是被线程所共享的
int g_val 0;
// 新线程
void *thread_routine(void *args)
{const char *name (const char *)args;while (true){cout 我是新线程, 我正在运行! : g_val g_val : g_val endl;sleep(1);}
}
int main()
{typedef unsigned long int pthread_t;pthread_t tid;int n pthread_create(tid, nullptr, thread_routine, (void *)thread one);assert(0 n);(void)n;while (true){cout 我是主线程, 我正在运行! : g_val g_val : g_val endl;sleep(1);}return 0;
}线程也一定要有自己私有的资源什么资源应该是线程私有的呢?
PCB属性私有要有一定私有上下文结构每一个线程都要有自己独立的栈结构-
2.与进程之间切换相比线程的切换
进程:切换页表虚拟地址空间切换PCB 上下文切换线程:切换PCB 上下文切换线程切换cache不用太更新但是进程切换全部更新 cache:高速缓冲存储器比CPU的寄存器慢些但是比内存块 软件存在一种属性叫做局部性原理当前访问的代码和数据那么它相邻的代码和数据也非常容易被访问到。 当多个线程切换时这些热点数据本来就是被线程所共享的线程切换时cache不用被切换。因为这部分数据线程PCB再怎么切换可能之前缓存的数据还是能用得上能命中所以缓存根本不用切换。(热点数据就是经常被访问到的数据) 如果是进程切换A进程代码和数据保存一大堆切换到B进程时上下文一保存那么之前cache里的缓存数据都失效新进程B需要重新加载到cache切换到旧进程A又要重新加载来回切换增加了很多成本与效率。 初识线程总结
进程 VS 线程 Linux进程是申请资源的基本单位而线程是进程里面的一个小执行流是CPU调度的基本单位。下图整个框里面是进程而线程是绿色的PCB执行流
线程的优点
创建一个新线程的代价要比创建一个新进程小得多与进程之间的切换相比线程之间的切换需要操作系统做的工作要少很多线程占用的资源要比进程少很多能充分利用多处理器的可并行数量在等待慢速I/O操作结束的同时程序可执行其他的计算任务计算密集型应用为了能在多处理器系统上运行将计算分解到多个线程中实现I/O密集型应用为了提高性能将I/O操作重叠。线程可以同时等待不同的I/O操作。 计算密集型应用(CPU加密解密算法等) VS I/O密集型应用(外设访问磁盘显示器网络) 线程的缺点 性能损失 一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多那么可能会有较大的性能损失这里的性能损失指的是增加了额外的同步和调度开销而可用的资源不变。 健壮性降低 编写多线程需要更全面更深入的考虑在一个多线程程序里因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的换句话说线程之间是缺乏保护的。 为什么一个线程出问题会影响其余线程进程信号信号是整体发给进程的它会向PID相同的执行流全部写入出错信号。 线程出异常本身就是进程出异常比如小组里面的成员删库跑路公司问责不仅仅要问责这个成员还需要问责整个小组。一个线程出异常导致整个进程的资源都被释放掉那么其余的线程赖以生存的资源已经没了所以也就只能释放 缺乏访问控制 进程是访问控制的基本粒度在一个线程中调用某些OS函数会对整个进程造成影响。 编程难度提高 编写与调试一个多线程程序比单线程程序困难得多
线程异常
单个线程如果出现除零野指针问题导致线程崩溃进程也会随着崩溃线程是进程的执行分支线程出异常就类似进程出异常进而触发信号机制终止进程进程终止该进程内的所有线程也就随即退出
线程用途
合理的使用多线程能提高CPU密集型程序的执行效率合理的使用多线程能提高IO密集型程序的用户体验如生活中我们一边写代码一边下载开发工具就是多线程运行的一种表现
Linux进程VS线程
进程和线程比较
进程是资源分配的基本单位线程是调度的基本单位线程共享进程数据但也拥有自己的一部分数据比如: 1.线程ID 2.一组寄存器 3.栈 4.errno 5.信号屏蔽字 6.调度优先级 线程的共享 进程的多个线程共享同一地址空间因此Text Segment、Data Segment都是共享的如果定义一个函数在各线程中都可以调用如果定义一个全局变量在各线程中都可以访问到除此之外各线程还共享以下进程资源和环境:
文件描述符表每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)当前工作目录用户id和组id 如有错误或者不清楚的地方欢迎私信或者评论指出