首页 > 其他分享 >用户态多线程实现的基本原理

用户态多线程实现的基本原理

时间:2023-06-19 10:05:15浏览次数:44  
标签:上下文 实现 基本原理 用户 线程 切换 多线程 内核


本文参考了用户态非抢占式线程库实现 一文以及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又要进出一次内核,而内核线程切换则只需要一次时钟中断,只进出内核一次即可。这么说来,用户态线程库的性能应该劣于内核态线程库。但是,注意到每次时钟中断所做的工作远远不止上下文切换这么简单,这应该是用户态线程库更优的原因吧。基于这个分析,如果应用需要创建的线程数并不多,二者应该性能相当。但是,一旦线程数巨大且切换频繁,用户态线程库的优势就能体现出来了。

标签:上下文,实现,基本原理,用户,线程,切换,多线程,内核
From: https://blog.51cto.com/maray/6510881

相关文章

  • std::thread 六:多线程&单例类
     为了避免单例类在多线程中重复的创建,下面提供了两种解决方法:1.互斥锁+双重检查2.std::call_once() 方法一:互斥锁+双重检查#include<iostream>#include<thread>#include<mutex>#include<list>usingnamespacestd;std::mutexmy_mutex;//创建一个单......
  • RBAC实战-配置用户操作集群权限(二)
    生成私钥cd/etc/kubernetes/pki(umask077;opensslgenrsa-outlucky.key2048)生成证书请求opensslreq-new-keylucky.key-outlucky.csr-subj"/CN=lucky"生成luckyca证书,获取APIServer信任opensslx509-req-inlucky.csr-CAca.crt-CAkeyca.key-CAcreatese......
  • linux 定时任务 crontab更改当前用户
    1、参考CentOS7定时任务crontab入门Centos利用crontab定时执行任务及配置方法2、crontab-lcrontab-e#prodbackupdatabase#02***cd/data/xxxxx&&/usr/bin/shyy_backup.sh#prodautoupdatemanagecode#*****cd/data/xxxxx/&&sour......
  • Java多线程-Lesson01-线程的创建
    线程创建的三种方式继承Thread类步骤:继承Thread类重写run()方法调用start()开启线程重写run()方法:@Overridepublicvoidrun(){for(inti=0;i<200;i++){System.out.println("run():"+i);}} run()方法里面就是我们多......
  • MongoDB4.0.0 远程连接及用户名密码认证登陆配置
    https://blog.csdn.net/qq_26896281/article/details/81206492参考文章:https://docs.mongodb.com/manual/tutorial/enable-authentication/https://docs.mongodb.com/manual/core/security-built-in-roles/https://blog.csdn.net/Keith003/article/details/80897085一、创建......
  • Windows Server 2022 多用户同时登录 开启 批处理
    使用批处理在WindowsServer2022上配置远程桌面服务和远程桌面会话主机的连接,您可以按照以下步骤进行操作:启用远程连接:regadd"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer"/vfDenyTSConnections/tREG_DWORD/d0/f配置远程桌面服务:dism/......
  • 查询Oracel 数据文件、数据库用户、删除表空间、删除用户等脚本
    select*fromdba_data_files;select*fromdba_users;--删除用户DROPUSERSYNC_PLUS_1cascade;--删除表空间droptablespaceSYNC_PLUS_ORCLPDB1includingcontentsanddatafiles;为人:谦逊、激情、博学、审问、慎思、明辨、笃行学问:纸上得来终觉浅......
  • Oracel 创建表空间、创建用户并设置密码及制定表空间、分配权限、创建角色、角色授权
    select*fromdba_data_files;select*fromdba_users;--删除用户--DROPUSERSYNC_PLUS_1cascade;--删除表空间--droptablespaceSYNC_PLUS_ORCLPDB1includingcontentsanddatafiles;/*createtablespacesync_plus_1datafile'F:\DB_FILES\ORAC......
  • 多线程开启gprof性能测试的简易方法
    用到gprof时才知道,原来gprof只能对主线程统计耗时。manual上也没写线程相关的问题啊?不过有现成的解决方案:http://sam.zoy.org/writings/programming/gprof.html该方案封装了pthread_create(),让线程初始化执行一个setitimer(ITIMER_PROF,...)。简易的方法是直接在代码中写个setit......
  • Linux启动时间优化-内核和用户空间启动优化实践
    启动时间的优化,分为两大部分,分别是内核部分和用户空间两大部分。从内核timestamp0.000000作为内核启动起点,到free_initmem()输出"Freeinginitmemory"作为内核启动的终点。借助于bootgraph.py对内核的kmsg进行分析,输出bootgraph.html和initcall耗时csv文件。在紧接着free_i......