加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.zhandada.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

用户级多线程的切换原理

发布时间:2022-10-27 16:02:34 所属栏目:Unix 来源:互联网
导读: 前言
线程分为用户级线程和内核级线程,这节我们先来讨论一下何为用户级线程以及用户级线程的底层原理。用户级线程和内核级线程
说到用户级多线程,我们有必要先来简单对比一下用户级线程和

前言

线程分为用户级线程和内核级线程,这节我们先来讨论一下何为用户级线程以及用户级线程的底层原理。用户级线程和内核级线程

说到用户级多线程,我们有必要先来简单对比一下用户级线程和内核级线程之间的区别。内核级线程,顾名思义,它的调度是依赖于操作系统的,即操作系统控制着内核级线程的切换,比如有A和B两个内核级线程,我们用户是不知道先执行哪个线程的代码和不知道什么时候切换到另一个线程执行代码的,这件事只有操作系统知道,我们无法干预。

用户级线程,顾名思义,它的调度是依赖于用户的想法的,比如有C和D两个用户级线程,我们用户可以先让A执行一段代码后,然后手动控制让其跳到B去执行一段代码,我们是清楚知道线程间的切换的。简单一句话来说就是:内核级线程是由操作系统进行调度的,用户级线程是由用户来控制调度的。

用户级线程

我们举例子,来进一步说明用户级线程切换的底层原理,还是记住那句话:用户级线程的切换是由我们用户来主动控制的。现在我们假设有线程1和线程2两个线程(图中红色的数字为内存的地址)

linux 线程切换_unix线程切换_net 线程池 (线程池)threadpool

可以看出,线程1中有A()和B()两个函数,执行流程为A()函数调用B()函数,B()函数执行完毕后返回到地址为104的语句继续往下执行;线程2中有C()和D()两个函数unix线程切换,执行流程为C()函数调用D()函数,D()函数执行完毕后返回到地址为304的语句继续往下执行。那么图中还有一个Yield()函数到底是什么东西呢,简单来说它就是我们用户主动来控制线程切换的一个函数,在线程1中调用Yield()函数,此时会切换到线程2,在线程2中调用了Yield()函数,此时又会回到线程1继续执行。因此,执行流程为下图所示。

net 线程池 (线程池)threadpool_linux 线程切换_unix线程切换

现在我们更加深入地去剖析整个切换过程到底发生了什么有趣的事。线程1运行:B() 为函数调用,此时将函数调用的下一条指令地址入栈,即104入栈(因为要记录函数调用结束后返回到哪里继续执行)。

unix线程切换_linux 线程切换_net 线程池 (线程池)threadpool

随即进入B()内执行 ——> 线程切换(用户级线程)函数Yield()也为函数调用(特殊函数调用),即将要执行Yield(),则204入栈,随即执行Yield() ——>跳至内存中地址为300的指令执行,此时即进行了线程切换。

net 线程池 (线程池)threadpool_linux 线程切换_unix线程切换

类似,执行C() ——> 调用D(),304入栈,即将执行Yield(),404入栈。

unix线程切换_net 线程池 (线程池)threadpool_linux 线程切换

随即执行线程2的Yield() ——> 切换至线程1执行204 ,之后B() 结束,弹栈,为404,即执行完后跳去地址为404处执行。而实际上我们开始说过,执行完B()后要按轨迹5返回线程1的地址为104处执行,而此时调用执行完进入线程2的404,出错。某线程中的普通函数调用(Yield是特殊函数调用)只能在本线程来回折腾,所以上述情况的普通函数调用会返回到另外的线程执行,这是错误的。出错原因是因为两个线程共用了一个栈,导致线程之间切换和内部运行出现错乱。因此,可以用两个栈解决这个问题,即分别为每一个线程分配一个独立的栈!还是上面的那个例子

net 线程池 (线程池)threadpool_linux 线程切换_unix线程切换

此时的栈不在是上面的那仅有的一个栈,而是线程1有一个栈,线程2也有一个栈,其中它们各自的栈地址存放于各自线程的TCB中,还有一个全局的栈指示变量,它的作用是指示当前用的是哪一个线程的栈。那么,线程1运行:B() 为函数调用,此时将函数调用的下一条指令地址入栈,即104入线程1中的栈,B()函数中执行Yield()函数,204入线程1中的栈,然后切换到线程2执行。

linux 线程切换_net 线程池 (线程池)threadpool_unix线程切换

线程2执行,同理,304入线程2的栈,404入线程2的栈。

linux 线程切换_net 线程池 (线程池)threadpool_unix线程切换

此时,两个栈的状态如下图

net 线程池 (线程池)threadpool_linux 线程切换_unix线程切换

线程2执行Yield()函数后,全局栈指示变量指向线程1的栈,此时执行出栈操作,出的是线程1的栈,弹出204,转到204执行语句,接着B()函数调用完后,return,继续在线程1的栈中(因为全局栈指示变量依然指向线程1的栈)执行出栈操作,弹出104,转回A()函数中的104语句,此时,就完美地解决了使用一个栈会导致乱跳转的问题!

linux 线程切换_net 线程池 (线程池)threadpool_unix线程切换

这一节,我们讲述了内核级线程和用户级线程的基本概念与区别、用户级线程的切换底层原理。关注小鲸融创,一起深度学习金融科技!

unix线程切换_linux 线程切换_net 线程池 (线程池)threadpool

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章