用户级线程

引入线程

如下图,映射表就是资源,因为映射表代表的是内存

  • 进程切换的时候只切换指令不切换资源,这就是线程的切换,也就是说在切换进程时,只切换线程,不切换资源,
  • 这样既有多个指令的切换,又切起来快,也就是线程的优点:既保留了并发的优点,又避免了进程切换的代价

在这里插入图片描述

  • 举例:
  • 如下图,打开一个网页,我们发现它先刷出文本,过一会儿图片也出来了
  • 如果是一个线程工作,它先用一段时间下载数据,下载好了之后突然很快的显示出来,如果是这样工作用户会感觉非常不爽,
  • 应该怎么工作呢? 一个线程它先下载文本数据,下载完后切出去,切到显示文本的进程,显示完文本后再切回去继续下载图片…
  • 为什么说这是一个线程而不是进程呢?
  • 服务器从网上接受到的数据放在缓冲区里,显示文本的时候也要从缓冲区里取,
  • 如果是进程的话,他们的地址是分离的,存和取都在不同的地方,就需要复制来复制去,就很麻烦,
  • 他们本就是合作关系,完全不需要地址分离,他们完全可以共享数据,这就是为什么线程的原因

在这里插入图片描述

  • 浏览器伪代码:
    在这里插入图片描述
Yield实现切换

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 一个栈

如下图,两个进程共用一个栈会不会有问题?我们走一遍程序
104;204;等代表压栈

  • 首先执行A,A中调用了B,104入栈;
  • 执行B,B中调用了Yield,204入栈;
  • 执行Yield,pc设为300,jmp到300的地方也就是C;
  • 执行C,调用了D,304入栈,;
  • 执行D,调用Yield,404入栈;
  • 执行Yield,因为这里是要切回去,所以找到的应该是204,pc设为204,jmp到B,
  • 接下来遇到了B的 “}” ,此时该要ret弹出栈了,弹出的是404,我们发现又跑回D了,这显然不是我们想要的结果,B执行完本应该要回到A,结果却跑到D去了,
  • 解决方法:用两个栈

在这里插入图片描述

  • 两个栈
  • 和上面一个栈不同的是Yield函数,这里用到了TCB线程控制块
  • 执行Yield时,会切换栈,保证每个线程操作的是自己的栈
  • 但是还是有问题
  • 执行D的Yield时,切换栈(esp就是物理寄存器)和pc后,jmp到204,此时遇到B的“}”,改ret出栈了,弹出204,我们会发现又到204,
  • 解决:去掉jmp 204;我们再从D的Yield走一遍,切换栈和pc后,此时遇到B的“}”,该ret出栈了,弹出204,又遇到B的“}”,ret出栈,这次弹出的是104…,这样就可以正常的执行了

在这里插入图片描述

  • 总结:两个线程的样子:两个栈,两个pcb,切换的pc在栈中
ThreadCreate

在这里插入图片描述

在这里插入图片描述

用户级线程的缺点

* 用户级线程是用户态,当它getData时,会请求网卡读写,
* 网卡是硬件啊,要访问硬件,必须要经过操作系统所以此时会进入内核,
* 当网卡阻塞的时候,此时内核就会切换到其他进程去,因为 内核看不到外面有线程,它就会切到其他进程,
* 此时浏览器将会白白一片,什么都不显示

在这里插入图片描述

  • 而核心级线程就不一样了
* 核心级线程的创建在内核中,要创建线程,就要进入内核,所以tcb也在内核中
* 这是执行getData时,假设阻塞了,但是缓冲区已经下载了一些数据,* * 此时可以切换到显示进程显示数据
* 所以内核级的线程并发性更好

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值