状态机
从毕业到现在都没有写过博客了,一是没什么大的收获,二是这段时间发生了太多事,从入职到这段时间,思想经历了各种斗争。今天终于有了点值得写的东西,就暂时放下思想斗争记录一下新发现吧。
以前写代码时从来只知道有状态机,但是从来没有用过,这段时间因为代码开的线程太多了,程序吃不消,经高人指点才发现其实可以用状态机来用一个任务来模拟多个相似任务。下面就来分析一下状态机实现多任务的原理。
一个完整的代码是由数据和代码组成,由同一个函数创建的多个线程在线程切换时仅仅是切换其中的数据共用其中代码。
可以实现这样一个纯代码函数,这个纯代码函数只根据参数的内容来执行与代码上下文无关,在模拟切换线程时仅切换一下函数参数即可。线程最重要的特点就是没执行完就可以由时钟中断进行切换,归根到底就是每次每个线程只执行一段程序,因此把一个函数分成几个块,每次每个模拟线程执行一块,这样就可以模拟出一个类似时间片轮转的多线程调度算法, 状态机恰好满足上面要求。语言描述总归是无力的,下面请看代码。
1 #include <stdio.h> 2 #include <assert.h> 3 4 struct fsm_param { 5 int next; 6 char *param; 7 }; 8 9 int fsm(struct fsm_param *param) 10 { 11 switch (param->next) { 12 case 0: 13 printf("%c", param->param[0]); 14 param->next = 1; 15 break; 16 case 1: 17 printf("%c", param->param[1]); 18 param->next = 2; 19 break; 20 case 2: 21 printf("%c", param->param[2]); 22 param->next = 3; 23 break; 24 case 3: 25 printf("%c", param->param[3]); 26 param->next = 4; 27 break; 28 case 4: 29 printf("%c", param->param[4]); 30 param->next = 5; 31 break; 32 case 5: 33 printf("\n"); 34 param->next = 6; 35 break; 36 default: 37 assert(!"Never arrive here"); 38 } 39 return 1; 40 } 41 42 int main() 43 { 44 int i; 45 struct fsm_param thread[2]; 46 47 thread[0].next = 0; 48 thread[0].param = "AAAA"; 49 thread[1].next = 0; 50 thread[1].param = "BBBB"; 51 52 do { 53 for (i = 0; i < 2; i++) 54 fsm(&thread[i]); 55 56 } while (thread[0].next != 6 && thread[1].next != 6); 57 return 0; 58 }
啥也不说了上图看效果,是不是和时间片轮转调度算法写出来的多线程一致呢?甚至我们可以更改调度算法哟!再次感叹一句,C语言博大精深啊!