用户态多线程实现的基本原理
来源:互联网 发布:淘宝画眉鸟活体 编辑:程序博客网 时间:2024/06/05 05:19
本文参考了用户态非抢占式线程库实现 一文以及GNU Pth 。前者是一种用户态线程库的简单实现,属于一个很好的demo,后者就是大家熟知的Pthread的用户态实现,比较完善。
Keywords: User-Space MultiThreading, Pth
所谓多线程,简单讲就是能够让几个不同的代码片段轮流执行。内核实现多线程的方法比较直观,在每次时钟中断到来时或者用户调用syscall陷入内核时进行上下文切换即可。用户态切换线程要解决两个问题:
1、时机,即何时切换线程?
2、方法,即怎样切换上下文?
为了决定切换时机,需要确定所设计的线程库是可剥夺(preemptive)的还是不可剥夺(non-preemptive)的。一般,用户态线程库都选择使用不可剥夺的设计方案,这么做的好处是将控制权交给用户,而用户最了解何时需要放弃执行权。这么做减少了系统切换次数,实现了最高的CPU利用率,非常适合用于科学计算环境。但是,另一方面这么做也存在缺点:其它线程的响应速度变慢,他们必须等到当前CPU放弃执行权后才能被执行。能不能将用户线程设计成可剥夺的呢?这应该也是可行的。每个用户线程运行一段时间后会被迫暂停执行,被动地将控制权交回给调度器。怎样才能“被迫暂停执行”?这是方法问题,下面就要讲到。
对于不可剥夺方式,需要用户编写程序的时候主动调用诸如thread_yeild(), thread_wai()之类的函数,这些函数会将当前用户线程的执行上下文保存起来,然后让调度器选择一个新的用户线程投入执行。底层操作系统提供了一些列的机制支持上下文的获得和切换,如setjmp,longjmp,getcontext,swapcontext等。用户态非抢占式线程库实现一文使用了前面两个函数,GNU Pth 使用了后面两个函数。可剥夺方式的实现需要更多的操作系统支持,如可以利用alarm函数周期性地产生用户态中断,每次中断到来的时候线程库进行线程切换。
单纯的用户态线程库一般都是基于一个单线程进程实现的,一旦用户线程阻塞,这个进程就被阻塞,进而导致整个用户态线程组得不到CPU。基于单进程实现的用户态线程库在SMP/多CPU环境下性能很差,多出来的核无法被线程库利用,这跟当前的微处理器架构发展趋势十分不符。为了解决这个问题,可以考虑使用一种混合结构:在少量内核线程的基础上实现大量的用户线程。
最后思考一个问题:为什么用户态线程库比内核态线程库具有更高的性能呢?其实用户态线程库同样离不开进入内核态这一过程,以getcontext,swapcontex实现方式为例,getcontext要进出一次内核,swapcontex又要进出一次内核,而内核线程切换则只需要一次时钟中断,只进出内核一次即可。这么说来,用户态线程库的性能应该劣于内核态线程库。但是,注意到每次时钟中断所做的工作远远不止上下文切换这么简单,这应该是用户态线程库更优的原因吧。基于这个分析,如果应用需要创建的线程数并不多,二者应该性能相当。但是,一旦线程数巨大且切换频繁,用户态线程库的优势就能体现出来了。
本文转自:http://blog.csdn.net/maray/article/details/4946245
- 用户态多线程实现的基本原理
- 用户态多线程实现的基本原理
- linux 多线程的实现的基本原理
- Java - 多线程的基本原理
- Java多线程运行机制的基本原理
- 用户态多线程的3种实现方式
- UPNP实现的基本原理
- 中断实现的基本原理
- dfs实现的基本原理
- 局域网实现监听的基本原理
- 局域网实现监听的基本原理
- 微信摇一摇实现签到的基本原理
- Android AsyncTask的实现基本原理
- 关于SPA实现的基本原理
- hash的基本原理与实现
- 二、 AsyncTask的实现基本原理
- 线程、多线程基本原理与两种实现方法
- 用ucontext实现简单的用户空间协作多线程
- JDK命名方式
- Linux系统函数学习之lseek
- [小代码]获得已安装应用程序的列表
- CAS向客户端传递参数乱码问题
- hibernate工作原理
- 用户态多线程实现的基本原理
- Python笔记——类定义
- linux 时间函数
- activity 与 service 数据的通信
- 引入cocos2D代码后的错误处理
- PostgreSQL学习手册(数据库维护)
- 数组递增遍历与递减遍历的效率
- typedef
- 在应用程序级别以外使用注册为 allowDefinition='MachineToApplication' 的节是错误的解决办法