参考转载地址:
Windows的纤程(Fiber)
以前学操作系统原理时,听说过用户级线程,但不知道是否有真实操作系统支持。今天在看《多核程序设计技术》时,发现原来Windows中就有这个东东,长见识了,拿来与大家分享。
Windows中提供的纤程(fiber)是一种用户级线程。与处于内核的线程不同,纤程完全包含在用户空间中,由用户自己进行调度。纤程对于Windows内核来说是透明的,Windows内核感觉不到纤程的存在。
可以把一个线程分解为多个子任务,由纤程来执行。但一个线程在同一时刻只能运行一个纤程,纤程并不能够带来更多的并行性。纤程的主要目的是为开发人员调度多个不需要并行执行的任务提供一个便捷的机制。
要使用纤程,首先需要把当前线程转换为一个纤程,这通过ConverThreadToFiber()函数实现。然后通过CreateFiber()创建新纤程,并需要指定纤程函数。创建好纤程后,可以通过SwitchToFiber()在线程间切换。
纤程函数的一个重要特征是不能退出。因为一旦一个纤程退出,该纤程所在的线程将退出,那么该线程中的所有其它纤程也将终止。
还可以通过DeleteFiber()函数删除一个纤程。如果当前正在运行的纤程调用DeleteFiber(),将会导致它所在线程退出。
关于纤程的详细内容,请参考MSDN中的“Fibers”。
还没有想到纤程的适用场合,这里仅提供一个《多核程序设计技术》中的例子(P102~103):
#define _WIN32_WINNT 0x400
#include <stdio.h>
#include <windows.h>
#define FIBER_COUNT 10
void *fiber_context[FIBER_COUNT];
VOID WINAPI fiberProc(void*);
int main()
{
int i;
int fibers[FIBER_COUNT];
for (i = 0; i < FIBER_COUNT; i++) {
fibers[i] = i;
}
fiber_context[0] = ConvertThreadToFiber(NULL);
for (i = 1; i < FIBER_COUNT; ++i) {
fiber_context[i] = CreateFiber(0, fiberProc, &fibers[i]);
if (fiber_context[i] != NULL)
printf("Fiber %d created\n", i);
}
for (i = 1; i < FIBER_COUNT; ++i) {
if (fiber_context[i] != NULL) {
SwitchToFiber(fiber_context[i]);
}
}
printf("Over\n");
}
void WINAPI fiberProc(void *fiber_nbr)
{
int nbr;
nbr = *((int*)fiber_nbr);
printf("Hello from fiber %d\n", nbr);
SwitchToFiber(fiber_context[0]);
}
程序运行结果:
Fiber 1 created
Fiber 2 created
Fiber 3 created
Fiber 4 created
Fiber 5 created
Fiber 6 created
Fiber 7 created
Fiber 8 created
Fiber 9 created
Hello from fiber 1
Hello from fiber 2
Hello from fiber 3
Hello from fiber 4
Hello from fiber 5
Hello from fiber 6
Hello from fiber 7
Hello from fiber 8
Hello from fiber 9
Over
总结:
例如当遇到同时连接多个数据库(DB2,ORACLE,MYSQL...)并根据情况进行自由切换这种需求.按原有方案可能会根据库的多少建立相应数量的线程(thread)长连接到数据库,并根据业务变化切换到不同的线程(thread)进行操作.而1个线程(thread)在Windows系统中默认占用1M内存,这样会占用很多内存,同时由于线程(thread)切换(context switch)效率低,大概需要上千乃至上万(cache完全错误)的时钟周期.所以性能会由于线程(thread)的不断增加逐渐递减.
同样的问题.多个数据库只要起一个线程(thread)进行长连接,在该线程(thread)中启动多个纤程(fiber),并根据业务的变化切换到不同的纤程(fiber)中,而纤程(fiber)切换耗时只会有几个时钟周期(待测).
从宏观上讲,将以前work 线程(thread)和help 线程(thread) 两种区分方式取消,改为由线程(thread)实现整体业务上的定向,通过线程(thread)获得CPU,并进行亲缘性优化,而具体详细的业务交由纤程(fiber)来实现.