[操作系统] 实现线程包的方式

【从零开始玩量化7】easyTrader: 自动化(程序化)交易利器 前面的文章,我们介绍了数据获取工具AKShare, 量化回测工具backtrader等,这一篇,介绍程序化交易工具easyTrader。作者网名食灯鬼,目前项目在Github上的star数已经有6.7k。这可能是目前,开源能找到的,最好用的程序化交易库了。本文介绍了easyTrader的简单用法,这个包还有很多功能,后续再继续写文章探究。 阅读详情

实现线程包的方式



1. 在用户空间实现

内核对线程包一无所知,从内核角度考虑,就是按正常单线程进程管理。每个进程需要有其专用的线程表,用来跟踪该进程中的线程。这些表和内核中的进程表类似,不过仅仅记录各个线程的属性,如每个线程的程序计数器,堆栈指针、寄存器和状态等,并由运行时系统管理。

优点:

  1. 用户级线程包可以在不支持线程的操作系统上实现。线程切换比陷入内核要快一个数量级。因为如果某个线程阻塞,线程表保存该线程的寄存器,然后查看表中可运行的线程,并且把新线程的保存值重新装入机器的寄存器中。只要堆栈指针和程序计数器被切换,新的线程即可立即投入运行。如果机器有一条保存所有寄存器的指令和另一条装入全部寄存器的指令,那么切换可以在几条指令内完成。另外,保存线程状态的过程和调度程序是本地过程,不需要内核调用。不需要陷阱,上下文切换,也不需要对Cache进行刷新。

  2. 允许每个进程有自己定制的调度算法。

  3. 扩展性:内核空间中内核线程需要一些固定表格空间和堆栈空间,如果数量过大,就会出现问题。

缺点:

  1. 阻塞系统调用:假设在没有任何击键之前,一个线程读取键盘,让该线程实际进行该系统调用是不可接受的。因为这会停止所有线程。使用线程的一个目标是,首先要允许每个线程使用阻塞调用,但是还要避免被阻塞的线程影响其他线程。有了阻塞系统调用,这个目标很难实现。

    改进:如果某个调用会阻塞,提前通知。例如在Unix中使用select允许调用者通知预期read是否会阻塞。如果有这个调用,那么read就可以被新的操作替代。首先进行select调用,然后只有在不会阻塞的情况下才进行read调用。如果read调用会被阻塞,有关的调用就不进行,代之以运行另一个线程。

  2. 如果一个线程引起页面故障(跳转到不在内存上的指令),内核由于不知道有线程存在,通常会把整个进程阻塞,直到磁盘I/O完成为止,尽管其他线程是可以运行的。

  3. 如果一个线程开始运行,那么在该进程中其他的线程就不能运行,除非第一个线程自动放弃CPU。在一个单独的进程内部,没有时钟中断,所以不可能用轮转调度。除非某个线程能够按照自己的意志进入运行时系统,否则调度程序没有任何机会。 可能的方法是让运行时系统请求每秒一次的时钟信号(中断),但是这样对程序也是生硬和无序的。不可能总是高频率地发生周期性的时钟中断。有可能扰乱系统使用的时钟,因为线程可能也需要时钟中断。

2.内核中实现

不需要运行环境,每个进程没有自己的线程表。相反,在内核中有用来记录系统中所有线程的线程表。当某个线程希望创建一个新线程或撤销一个已有线程时,它进行一个系统调用,这个系统调用通过对线程表的更新完成线程创建或撤销工作。

优点:

  1. 所有能够阻塞线程的调用都以系统调用的形式实现,当一个线程阻塞时,内核根据其选择, 可以运行同一个进程中的另一个线程(若有就绪线程)或者运行另一个进程中的线程。而在用户级线程中,运行环境始终运行自己进程中的线程,直到内核剥夺它的CPU为止。

    因为在内核中创建或撤销线程代价较大,某些系统采取的处理方式为,回收线程,当某个线程被撤销时,把它标志为不可运行的,但是内核数据结构没有收到影响,在稍后创建新线程时,就重新启动某个旧线程,节省开销。

缺点:

  1. 当一个多线程进程创建新的进程时,新进程是拥有与原进程相同数量的线程还是应该只有一个线程。取决于进程下一步要做什么。如果要启动一个新程序,一个线程或许就可以。如果要继续运行,则应该复制所有线程。实现复杂。

  2. 信号:因为信号是发给进程而不是线程的,当一个信号到达时,应该如何决定由哪一个线程处理它。

3. 混合实现

使用内核级线程,一个内核级线程可能对应多个用户级线程

4. 调度程序激活机制

模拟内核线程的功能,但是为线程包提供通常在用户空间中才能实现的更好的性能和更大的灵活性。例如:如果用户线程从事某种系统调用时是安全的,那就不应该进行专门的非阻塞调用或进行提前检查。如果线程阻塞在某个系统调用或页面故障上,只要在同一个进程中有任何就绪的线程,就应该有可能运行其他的线程。

避免了用户空间和内核空间之间的不必要转换。 例如:如果某个线程由于等待另一个线程的工作而阻塞,此时没有理由请求内核,这样就减少了内核-用户转换的开销。用户空间的运行环境可以阻塞同步的线程而另外调度一个新线程。

内核可以给每个进程安排一定数量的虚拟处理器,并且让用户空间运行环境将线程分配到处理器上。当这一机制用在多处理器中时,虚拟处理器可能成为真实CPU。分配给每个进程的虚拟处理器的初始数量是一个,但是该进程可以申请更多的处理器并且在不用的时候退回。内核也可以取回已经分配的虚拟处理器,以便把它们分给需要多处理器的进程。

思路:当内核了解到一个线程被阻塞之后,内核通知该进程的运行时环境,并且在堆栈中以参数形式传递。有问题的线程编号和所发生事件的一个描述。内核通过在一个已知的起始地址启动运行时系统,从而发出了通知,称为上行调用(upcall)。把当前线程标记为阻塞并从就绪表中取出另一个线程,设置其寄存器,然后再启动之。稍后,当内核知道原来的线程又可运行时,内核就又一次上行调用运行时系统,通知它这一事件。此时运行时系统可以立即重启原来被阻塞的线程,或者放入就绪表中稍后运行。

在某个用户线程运行的同时发生一个硬件中断时,被中断的CPU切换进核心态。如果被中断的进程对引起该中断的时间不感兴趣,比如是另一个进程的I/O完成了,那么在中断处理程序结束之后,就把被中断的线程恢复到中断之前的状态。相反,若是该进程对中断感兴趣(如该进程中某个线程所需资源到达),那么被中断的线程就不再启动,代之为挂起被中断的线程。而运行时系统则启动对应的虚拟CPU,此时被中断线程的状态保存在堆栈中。随后,运行时系统决定在该CPU上调度哪个线程:被中断线程,新就绪线程,或第三种选择。

在层次系统结构中,通常n层提供n+1层可调用的特定服务,但是n层不能调用n+1层中的过程,但是上行调用不遵守这个原理。

5. 弹出式线程

一个消息的到达导致系统创建一个处理该消息的线程(传统方法为将进程或线程阻塞在receive系统调用上)

优点:

  1. 因为是新线程,没有必须存储的寄存器、堆栈等内容。每个线程从全新开始,可以快速创建。

缺点:

  1. 需要提前计划,哪个进程中的线程线运行。如果系统支持在内核上下文种运行线程,线程就有可能在那里运行。

6.单线程程序多线程化

  1. 对于全局变量:

    • 为每个线程赋予其私有的全局变量(全局变量的私有副本)。避免冲突。但是多数程序设计语言只具有表示局部变量和全局变量的方式,而没有中间形式。所以想使用这种方法,有可能为全局变量分配一块内存,并将它传送给线程中的每个过程作为额外的参数。

    • 引入库过程,将特殊存储区上替全局变量分配存储空间。无论该存储空间分配在何处,只有调用线程才可访问其全局变量。如果另一个线程创建了同名的全局变量,由于在不同的存储单元上,所以不会与已有变量冲突。但是有许多库过程不是可重入的。(可重入的意思为程序在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该程序不会出错,即子程序正在运行时,执行线程可以再次进入并执行它,仍然获得符合设计时预期的结。不可重入即意味着,不同任务调用这个过程时可能修改其他任务调用这个过程的数据,从而导致不可预料的后果)

    • 给每个过程提供一个包装器,该包装器设置一个二进制位从而标志某个库处于使用中。在先前调用还没有完成之前,任何试图使用该库的其他进程都会被阻塞。

  2. 信号:

    • 一些信号是线程专用的,但是另外一些并不是,当线程完全在用户空间实现时,内核根本不知道有线程存在,所以很难将信号发送给正确线程。

    • 一些信号不是线程专用,那么哪个线程该捕捉它。指定线程?所有线程?弹出式线程?如果某个线程修改了信号处理程序,是否需要通知其他线程。如果一个线程想捕捉一个特定的信号,而另一个线程却想用这个信号终止进程,会发生什么。

  3. 堆栈的管理:当一个进程堆栈溢出时,内核只是自动为该进程提供更多堆栈。当一个进程有多个线程时,就必须有多个堆栈。内核不了解所有堆栈,无法为他们提供增长,直到堆栈出错。内核可能没有意识到内存错误是和某个线程栈的增长有关系的。

参考书目:现代操作系统第三版

Python | 处理CMIP6 NC数据,以tas为例 各位同学,一般在文章最后一章我们可能会做不同气候情景下变量的未来时空变化特征,类似上图。从cmip6下载的nc数据常需要转换格式、裁剪到研究区和重采样等,本期代码可以解决这类问题。 阅读详情

相关推荐

BambuStudio学习笔记:OpenCSG - 实时构造实体几何(CSG)渲染的 OpenGL 方案

**OpenCSG** 是一个基于 **OpenGL** 的 **构造实体几何(CSG)** 实时渲染库,通过 **深度剥离算法** 实现布尔运算(并集、交集、差集)的可视化。其核心目标是简化复杂几何体的交互式建模,适用于 CAD 原型设计、3D 打印预览、教育工具等场景。

zzzkk2009的专栏 928

java 线程包_Java面试总结(多线程包的使用)

CountDownLatch的用法final CountDownLatch latch = new CountDownLatch(N);for(int i=0;inew Thread(new Runnable(){@Overridepublic void run(){System.out.println("线程 "+Thread.currentThread().getName()+" 执行完毕")...

weixin_36393744的博客 226

13 万字 C 语言从入门到精通保姆级教程2021 年版

13 万字C语言保姆级教程,从入门到精通。

李南江 61万+

多线程current包

编写多线程的程序一直都是一件比较麻烦的事情,要考虑很多事情,处理不好还会出很多意想不到的麻烦。加上现在很多开发者接触到的项目都是打着企业级旗号的B/S项目,大多数人都很少涉及多线程,这又为本文的主角增加了一份神秘感。 讲到Java多线程,大多数人脑海中跳出来的是Thread、Runnable、synchronized……这些是最基本的东西,虽然已经足够强大,但想要用好还真不容易。从JDK ...

hongweideng的专栏 524

PP-OCRv6 ONNX部署的官方和手搓方案

PP-OCRv6 基于全新设计的 PPLCNetV4 统一骨干网络,提供 tiny、small、medium 三档模型,分别面向端侧/IoT、移动端/桌面端、服务端场景。在内部多场景综合评估集上,PP-OCRv6_medium 相比 PP-OCRv5_server 识别精度提升 5.1%、检测精度提升 4.6%,同时 GPU 推理速度提升 2.37×;以仅 34.5M 参数的规模,精度超越 Qwen3-VL-235B、GPT-5.5 等大型视觉语言模型。

懒人的技术笔记 1888

储能EMS工作原理深度剖析:功率分配与充放电策略的底层逻辑

储能EMS的功率分配与充放电策略,是其智能化的集中体现。功率分配更像一个“执行指挥官”,关注如何将总任务高效、公平、安全地分解到每个士兵(PCS/电池簇);而充放电策略则像“总参谋长”,基于战场情报(市场、电网、自身状态)制定最优的作战计划。AI强化学习策略:让EMS通过与复杂环境不断交互,自主学习最优策略,适应不确定性。数字孪生与仿真:在虚拟空间中提前验证策略,评估风险,实现预防性控制。跨站协同优化:多个储能站的EMS通过云平台协同,参与区域电网甚至跨省市场的联合优化调度。

小帽子的博客 375

BlockingQueue理论普

BlockingQueue 简介: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列。 常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中

修复bug生成bug 412

《MPDIoU:边界框回归的高效革新与YOLOv8集成实战指南》

摘要: MPDIoU(多优先级距离IoU)通过引入中心距离、形状差异和尺度变化的三步优化策略,解决了传统IoU在目标检测中的尺度敏感、收敛低效和场景局限问题。相较于GIoU、DIoU等主流方法,MPDIoU在精度、速度和鲁棒性上实现全面提升,尤其在复杂场景和小目标检测中表现突出。通过代码集成和训练优化,MPDIoU在YOLOv8中显著提升COCO数据集AP指标,并在智能安防(密集行人检测)和工业质检(微小缺陷定位)等垂直领域验证了其应用价值。未来研究方向包括动态权重调整和多模态融合,进一步拓展边界框回归的精

m0_64661770的博客 158

java 线程包_Java 多线程——工具包

JUC首先来说说synchronized的有什么缺点。它非常的死板。要么获取锁,要么等待锁,而且我们无法知晓此时这个锁有没有被人拿到,也不知道某个线程是否是上锁状态。只有悲观锁、排他锁,没有乐观锁、共享锁。有些资源允许很多线程去读,但是只允许一个线程写,这样的锁叫做共享锁。悲观锁就是做某个操作必须要拿到一个锁。乐观锁就是先去把一个任务做完,但由于多个线程竞争这个操作没有正确完成,那就重新做一遍,直...

weixin_29571873的博客 656

树莓派 RP2350B 开发环境搭建

本文介绍了树莓派RP2350B开发环境的搭建过程。

张一西的博客 286

Python爬虫逆向案例:某云片滑块验证码分析-滑动验证码

今天我们看个滑块。

2201_76125393的博客 1034

线程是如何实现的?

本文是《深入理解操作系统》第五章,从本章开始将开启第二个重要的主题:线程,这一章也是进程这一重要概念的延续。彻底理解线程对程序员来说极为关键,本章就从程序员的角度来讲解到底什么是线程、操作系统是如何实现线程。本文承接上文《程序员应如何理解线程》,以下为本篇目录:进程的实现:PCB在用户态实现线程在内核态实现线程Linux中的线程实现总结进程的实现:PCB在用户态实现线程在内核态实现线程Linux中的线程实现总结

luoganttcc的博客 1507

26、特洛伊木马:威胁与防范

本文详细介绍了多种常见的特洛伊木马,包括RegForm、ProMail和远程访问特洛伊木马(RATs),并分析了其工作原理与危害。重点讲解了著名RATs如Back Orifice、SubSeven和The Thing的技术特点,揭示了黑客编写特洛伊木马的常用语言与方法。同时,提供了有效的防范策略,如谨慎获取软件、使用回滚程序、杀毒软件、防火墙及反特洛伊木马程序,并通过流程图展示了防御机制。旨在帮助用户识别威胁并加强系统安全防护。

e3f4g5的博客 88

Java——多线程

本文总结Java多线程的相关核心要点

謬熙的博客 1334

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

操作系统:线程实现方式

线程的实现方式影响着线程的性能和应用的设计。用户级线程提供了高效的线程操作,但在系统调用阻塞和多处理器利用方面有限制。内核级线程虽然在性能上有一定的开销,但能更好地支持多核处理器和避免单个线程阻塞导致整个进程阻塞的问题。混合实现试图结合两者的优点,提供更灵活的线程管理策略。开发者在设计应用时,需要根据应用的特点和需求,选择合适的线程实现方式。

坚定目标,超越自我 1287

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

线程的3种实现方式

线程的3种实现方式 在引入线程的操作系统中,进程是资源分配的基本单位,线程是独立调度的基本单位。在同一进程中,线程的切换不会引起进程切换。在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。 线程分为两种: 名称 描述 用户级线程(User-Level Thread, ULT) 由应用程序所支持的线程实现, 对内核不可见 ...

Mr.Phoebe的专栏 1万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

线程的实现方式总结

线程的实现方式共有四种,第一种是继承Thread抽象类;第二种是实现Runnable接口;第三种是实现Callable接口;最后一种是通过线程池创建线程。写一个类去继承Thread类,重写其中的run()方法,然后调用start()方法启动线程。写一个类去实现Runnable接口,重写其中的run()方法;用用实现Runnable接口的对象作为参数实例化一个Thread对象,调用Thread类的start()方法来启动线程。实现Runnable接口比继承Thread类所具有的优势:1. 适合多个相同的程序代

blanceage的博客 6653

线程的四种实现方式

1.继承Thread类 一个类继承Thread类,重写run()方法,调用Thread类中的start()方法启动线程。 2.实现Runnable类 自定义类实现Runnable接口,重写run()方法;用实现Runnable接口的对象作为参数实例化一个Thread对象,调用Thread类的start()方法来启动线程 实现Runnable接口比继承Thread类所具有的优势: 1. 适合多个相同的程序代码的线程去共享同一个资源。 2. 可以避免java中的单继承的局限性。 3...

weixin_46217160的博客 9768

【操作系统】线程实现方式(内核级线程、用户级线程)

线程实现方式(内核级线程、用户级线程)        根据操作系统内核是否对线程可感知,可以把线程分为内核线程和用户线程。        内核线程建立和销毁都是由操作系统负责、通过系统调用完成的。在内核的支持下运行,无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。        用户级线程仅存在于用户空间中,此类线程的创建、撤销、线程之间的同步与通信功能

Cout_Sev 4206

操作系统(十二)线程的实现方式、多线程模型

2.1.6 线程的实现方式、多线程模型 目录 2.1.6 线程的实现方式、多线程模型 2.1.6.1 线程的实现方式 2.1.6.2 多线程模型 2.1.6.1 线程的实现方式 线程已在许多系统中实现,但各系统的实现方式并不完全相同。在有的系统中,特别是一些数据库管理系统,所实现的是用户级线程;而另一些系统所实现的是内核级线程; 还有一些系统如 Solaris 操作系统,则同时实现...

qq_40608137的博客 1403

操作系统多线程实现_操作系统中的线程实现

操作系统多线程实现Each process has an address space. There is one thread of control in every traditional OS. Sometimes, it is viable to have multiple threads of control in the similar address space which is ru...

cumtb2002的博客 1133

操作系统 线程的实现

线程的实现 主要有三种线程的实现方式: 用户线程:在用户空间实现; POSIX Pthreads, Mach C- threads, Solaris threads 内核线程:在内核中实现; Windows,Solaris, Linux 轻量级进程:在内核中实现,支持用户线程 Solaris(LightWe ight Process) 一个或多个用户线程可以对应多个或一个内核线程 用户线程 在用户空间实现的线程机制,它不依赖于操作系统的内核,由一组用户级的线程库函数来完成线程的管理,包括进程的创建、终止、同

Azadoo的博客 835

Java线程和操作系统线程的关系

1.操作系统线程模型1.1 线程实现在用户空间下 当线程在用户空间下实现时,操作系统对线程的存在一无所知,操作系统只能看到进程,而不能看到线程。所有的线程都是在用户空间实现。在操作系统看来,每一个进程只有一个线程。过去的操作系统大部分是这种实现方式,这种方式的好处之一就是即使操作系统不支持线程,也可以通过库函数来支持线程。 我们换一种通俗的方式来讲解这段话,首先就是在这在模型下,程序员需要自己实

CringKong的博客 2万+

实现线程的两种方式

起初,操作系统中只有进程的概念,人们那时候对并发没有太高的要求。后来有些人想提高程序的井发,这才有了线程这一新生事物。任何新生事物在诞生之初都会被小心谨慎地对待,人们提出线程的需求时,操作系统也抱着“围观”的心态不敢轻举妄动,只能坐看其发展,真正待需求明朗时才会在操作系统一级来实现。想想也是,如果稍微有个新需求就往内核里面塞,内核开发成本很高不说,至少内核中肯定有很多“不切实际”的功能,所以人们还是能够体谅操作系统研发厂商的. 为此,既然不能说服操作系统支持线程,人们只好在用户进程内想办法。所以,线程的实现

qq_43811102的博客 1082

线程以及的线程实现方式

操作系统—线程 1、什么是线程 - 有部分进程需要同时做很多事,引入线程来增加并发度 - 线程是程序执行流的最小单位,进程之间可以并发执行,进程内部的各个线程也可以并发的执行。 - 引入线程之后,进程就只作为除cpu之外的系统资源的分配单元(打印机) 2、线程机制带来的变化(对比传统的) - 进程变成资源分配的基本单位,线程是调度的基本单位 ,线程之间可以实现并发。 - 提高了并发度 线程的切换不需要切换进程环境,系统开销减小 3、线程的属性: - 线程不拥有系统的资源,共享的是进程的系统

qq_43243907的博客 178

【操作系统线程实现方式与多线程模型】

用户级线程的优点是轻量级,创建和切换开销小,但缺点是不能充分利用多核处理器,因为操作系统无法将用户级线程映射到多个内核上。一对一模型是一种将每个用户级线程映射到一个内核级线程的方式,每个用户级线程都有一个对应的内核级线程。多对多模型是一种将用户级线程映射到内核级线程的方式,它允许应用程序创建多个用户级线程,并将它们映射到多个内核级线程上。多对一模型是一种将多个用户级线程映射到一个内核级线程的方式,所有用户级线程共享一个内核级线程。操作系统线程的实现方式可以分为两种主要模型:用户级线程和内核级线程。

武帝为此的博客 778
上一篇: [操作系统] 进程与线程
下一篇: [操作系统] 进程间的通信
LLLZHLIU
博客等级 码龄10年 19粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值