文章目录
一、线程是什么?
在一个进程中,可以有多个指令序列在执行,这些指令序列共享进程的资源(进程代码、进程数据、进程映射表等)。这些进程中的多个执行的指令序列称为线程。线程相比进程更轻量化,启动更快,且线程之间的切换更加容易,因为线程之间的切换只用切换指令序列,内存映射表不变,而进程之间的切换要切换内存映射表。
二、 用户级线程的切换
网页浏览器访问网站时会启动多个线程,比如一个线程向站点服务器请求数据,一个线程将数据显示在页面上。上图代码创建了两个线程,分别用于实现这两种功能。要想实现(伪)并发需要将线程交替执行,在用户态下这种交替执行通过调用yield函数执行。
1. yield函数如何实现切换?
用堆栈
如果两个执行序列用一个堆栈,首先A函数中调用B函数,先将地址104压入堆栈,接着跳转到B函数执行。在B函数中调用Yield()切换线程,则将地址204压入堆栈,跳转到C函数执行。C函数中调用D函数时,将地址304压入堆栈,跳转到D函数执行。在D函数中调用Yield()切换线程时,假定Yield函数能找到跳回上个线程所需的地址204,但在跳回去后,B函数执行完,右花括号在编译时相当于ret,会将地址404弹出返回,这会导致原本该跳回A函数执行的操作变为跳回D函数执行,出现问题了。
每个指令序列的函数调用是在指令序列内部发生的事,因而每个指令序列应该有属于自己的栈,解决办法是每个线程都有一个独立的堆栈。