Windows 纤程/协程
Windows下 纤程/协程
- 理论知识,立足根本
- 使用须知
- 代码
写这篇文章的原因是,很多框架/库都有协程/纤程的支持,比如python的gevent,PHP 的swoole等等,但是具体是什么样的呢?为什么协程方式性能会更好?很多初学者听个词,听风就是雨,把协程和IO能混成一个概念。
理论知识,立足根本
在Windows2000 / XP中,纤程(fiber)相当于用户级别的线程或轻进程.纤程由Win32库函数支持, 对核心是不可见的.纤程可以通过SwitchToFiber显示至另一合作纤程, 以实现合作纤程之间的协同.
纤程包含独立的目态栈, 寄存器状态的控制信息.目态控制的纤程转接要求较高的编程经验.由于纤程属于目态对象, 一个纤程被封锁意味着所在线程被封锁.应用程序可以通过ConvertThreadToFiber将线程转换为纤程.与线程对比, 纤程具有切换速度快的特点.
Microsoft公司给Windows添加了一种纤程,以便能够非常容易地将现有的UNIX服务器应用程序移植到Windows中。UNIX服务器应用程序属于单线程应用程序(由Windows定义),但是它能够为多个客户程序提供服务。换句话说, UNIX应用程序的开发人员已经创建了他们自己的线程结构库,他们能够使用这种线程结构库来仿真纯线程。该线程包能够创建多个堆栈,保存某些C P U寄存器,并且在它们之间进行切换,以便为客户机请求提供服务。
显然,若要取得最佳的性能,这些UNIX应用程序必须重新设计,仿真的线程库应该用Windows提供的纯线程来替代。然而,这种重新设计需要花费数月甚至更长的时间才能完成,因此许多公司首先将它们现有的UNIX代码移植到Windows中,这样就能够将某些应用软件推向Windows市场。
而协程性能比线程更好的主要原因在于:
- 线程是在系统内核中实现的,纤程是在用户模式下实现的,内核对纤程一无所知,内核会根据我们定义的算法来对纤程进行调度。
一个线程可以包含一个或多个纤程。
使用须知
使用纤程的第一个步骤是将已有的线程转换为一个纤程。ConvertThreadToFiber这个函数会为纤程的上下文分配内存,这个上下文的构成是:
- 一个用户自定义的值
- 结构化异常处理链的头
- 纤程栈的顶部和底部的内存地址
- 某些CPU寄存器,其中包括栈指针、指令指针以及其他寄存器
当我们分配了纤程执行上下文并对其进行初始化之后,还必须将执行上下文的地址与线程关联起来。这样我们就将线程转换成了一个纤程,该纤程在这个线程中执行。
其实,除非我们打算创建更多的纤程,并让它们在同一个线程中运行,否则没有理由将一个线程转换为纤程。
- 使用ConverThreadToFiber(Ex)将当前线程转换到纤程,这是纤程F1
这里说一下ConverThreadToFiber和ConverThreadToFiberEx的区别
ConverThreadToFiber这个函数会为纤程的执行上下文分配(大约200个字节)的内存,这个执行上下文由下列元素构成:
·一个用户自定义的值,它被初始化给ConverThreadToFiber的pvParam参数。
·结构化异常处理链的头
·纤程栈的顶部和底部的内存地址(当我们将一个线程转换为一个纤程的时候,这同时也是线程栈)
·某些CPU寄存器,其中包括栈指针,指令指针以及其他寄存器
默认情况下x86系统中,CPU的浮点信息不属于CPU寄存器的一部分,不会每个纤程都维护一份,因此如果纤程需要执行浮点操作,那将会导致数据被破坏。
为了覆盖系统默认的行为,我们应该调用新的ConverThreadToFiberEx函数,它允许我们在dwFlags参数中传入FIBER_FLAG_FLOAT_SWITCH标志
- 定义一个纤程函数,用于创建一个新纤程
- 纤程F1中调用CreateFiber(Ex)函数创建一个新的纤程F2
- SwitchToFiber函数进行纤程切换,让新创建的纤程F2执行
- F2纤程函数执行完毕的时候,使用SwitchToFiber转换到F1
- 在纤程F1中调用DeleteFiber来删除纤程F2
- 纤程F1中调用ConverFiberToThread,转换为线程
- 线程结束
代码
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <tchar.h>
#define FIBER_COUNT 2
LPVOID g_lpFiber[FIBER_COUNT] = {};
VOID WINAPI FiberFun(LPVOID pParam) //纤程函数的返回类型为VOID,并不是因为返回值没有意义,而是因为这个函数不应该返回!如果纤程函数返回,那么该线程以及它所创建的所有纤程都将立即被销毁
{LPCTSTR szParam1 = (LPCTSTR)pParam;LPCTSTR szparam2 = (LPCTSTR)GetFiberData();TCHAR szMsg[100] = { 0 };_stprintf_s(szMsg, TEXT("参数1:%s, 参数2:%s。\n"), szParam1, szparam2);//szParam1和szparam2一样的//OutputDebugString(szMsg);std::wcout.imbue(std::locale("", LC_CTYPE));std::wcout << szMsg;SwitchToFiber(g_lpFiber[0]);//必须切换回主线程程序才能继续执行,不然会卡在这里程序无法退出
}int main()
{g_lpFiber[0] = ConvertThreadToFiber((LPVOID)_T("我是ConvertThreadToFiber的参数\n"));g_lpFiber[1] = CreateFiber(0, FiberFun, (LPVOID)_T("我是纤程的参数"));SwitchToFiber(g_lpFiber[1]);//切换到g_lpFiber[1]LPCTSTR szParam = (LPCTSTR)GetFiberData();std::wcout.imbue(std::locale("", LC_CTYPE));std::wcout << szParam;BOOL bCftt = ConvertFiberToThread();//转回线程if (bCftt) {DeleteFiber(g_lpFiber[1]);}std::cout << "Hello World!\n";
}
我们完全可以在IO多路复用中使用协程,让我们自己定义如何调度这些方法。
Windows 纤程/协程相关推荐
- Kotlin协程 - - - 协程的简单使用
一.协程介绍 1.简介 协程是一种并发设计模式,您可以在 Android 平台上使用它来简化异步执行的代码.协程是在版本 1.3 中添加到 Kotlin 的,它基于来自其他语言的既定概念. 在 And ...
- 进程 线程 协程_进程 线程 协程 管程 纤程 概念对比理解
不知道是不是我自己本身就有那么一丝丝的密集恐惧,把这么一大堆看起来很相似很相关的概念放在一起,看起来是有点麻,捋一捋感觉舒服多了. 相关概念 任务.作业(Job,Task,Schedule) 在进程的 ...
- Thread(线程)、Fiber(纤程)、coroutine(协程) 、绿色线程(GreenThread)
计算机有进程,线程和协程.前两者大家都知道,很常见的玩意.而协程,则是基于线程之上的,自主开辟的异步任务,很多人更喜欢叫它们纤程(Fiber),或者绿色线程(GreenThread). 进程 为了使多 ...
- Day10-Python3基础-协程、异步IO、redis缓存、rabbitMQ队列
内容目录: Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko S ...
- python进程\协程\异步IO
进程 学习python中有什么不懂的地方,小编这里推荐加小编的python学习群:895 817 687有任何不懂的都可以在里面交流,还有很好的视频教程pdf学习资料,大家一起学习交流! Python ...
- python异步和进程_12.python进程\协程\异步IO
进程 Python中的多线程无法利用多核优势 , 所以如果我们想要充分地使用多核CPU的资源 , 那么就只能靠多进程了 multiprocessing模块中提供了Process , Queue , P ...
- Python 异步 IO 、协程、asyncio、async/await、aiohttp
From :廖雪峰 异步IO :https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152 Python Async/Awai ...
- linux的进程/线程/协程系列5:协程的发展复兴与实现现状
协程的发展复兴与实现现状 前言 本篇摘要: 1. 协同制的发展史 1.1 协同工作制的提出 1.2 自顶向下,无需协同 1.3 协同式思想的应用 2. 协程的复兴 2.1 高并发带来的问题 2.2 制 ...
- 进程,线程和协程 并行与并发
一.进程 进程的出现是为了更好的利用CPU资源使到并发成为可能. 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费.聪明的老大 ...
最新文章
- 一个页面多个swiper问题解决
- mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比,于是写了个插件。
- PyQt5 关于自动补全 QCompleter
- 超400万用户的Chrome截图插件下架始末
- AcWing 841. 字符串哈希(字符串Hash)
- 《 Programming Collective Intelligence》案例介绍与分析——Making Recommendations
- 60行C代码的shell领略Unix哲学之美
- 0-1整数规划的求解思路整理
- 不堪回首的真实往事:我和一个骗子网友的两年矛盾纠葛
- Tik Tok直播:如何做好TikTok直播?
- 如果有一天我不更新博客了
- 重要的不是你正在做什么,而是你在想什么
- 辰视将携3D视觉技术及各领域解决方案参加华南工博会国际机器视觉展
- 【LaTeX】IEEE会议模板中插入双栏图片(解决报错:Undefined control sequence. \subfloat
- 素材管理神器 Eagle 下载安装使用教程
- 辣味人生:享受有辣而不辣
- 在职人员如何发表期刊论文
- word 参考文献 交叉引用 自动更新
- 北大软微计算机应用基础真题,北京大学软微考研参考书、考研真题及复习经验...
- dao层(dao层的作用)
热门文章
- 2022/04/29 第一次晋升答辩总结
- 理论+实操:K8S搭建dns内部服务与控制器controlls五种模式
- 迁移学习---举一反三
- thunderbird收件箱只显示邮件个数,无法打开邮件
- SpingBoot—微服务初始化资源方法
- 低密度奇偶校验码(LDPC)
- 【JavaSE系列】世界上“最好的语言”——认识Java编程语言
- Win7下SQLite安装配置与使用方法详解
- 程序员抛弃大厂涌进工厂!南洋理工海归:这里上班比整天盯着电脑有意思的多!...
- 项目学习 —— 图书商城后台管理