多线程问题,对初学者来说,会常常感到神秘。特别想知道它里面到底是怎么执行的;遇到问题时,又会觉得十分迷惑。
前面的例子,swap 语句串扰执行问题,实现了一个assign指令的解释器。现在就借用它的代码,用解释程序演示一下多线程是怎么执行的。
现在注意力集中到考虑,以swap(a,b):, swap(a,c):, 为蓝本的2个线程,每个线程各执行相应的swap代码10次。线程的数据结构是:
struct thread_proc {int ecount;int count;struct assign **ins;int n;int cur;
};
其中,用ecount表示thread的任务是执行10次,count从 0计数,到ecount执行结束。ins照旧,存放swap(a,b):或swap(a,c):的指令。n是指令的长度。cur是thread当前执行到的位置。
线程初始化为各执行swap(a,b):或swap(a,c):10次:
struct assign *swap_ab_ins[3]= {&all_assigns[0], &all_assigns[1], &all_assigns[2]
};
struct assign *swap_ac_ins[3]= {&all_assigns[3], &all_assigns[4], &all_assigns[5]
};
struct thread_proc thread2[2]=
{{10, 0, swap_ab_ins, 3, 0},{10, 0, swap_ac_ins, 3, 0},
};
线程执行,每个片断执行1~3个线程指令:
void execute(struct thread_proc *t, int n)
{int i;int pos;struct assign **a;a = t->ins;if(t==&thread2[0]) {printf("swap(a,b):");}else {printf("swap(a,c):");}for(i=0; i<n; i++) {if(i) printf("\t");pos = t->cur;print_ins_nl(a[pos], 0);*(a[pos]->left) = *(a[pos]->right);printf("\t");print_vars(&result); printf("\n");t->cur++;if(t->cur>=t->n) {t->count++;t->cur=0;}if(finish(t)) break;}
}
调度程序,选择"下一个"需要执行的线程,交错执行每个线程:
struct thread_proc *run;
int finish(struct thread_proc *t)
{return t->count>=t->ecount;
}int sched()
{struct thread_proc *next;if(run== &thread2[0]) {next= &thread2[1];} else {next= &thread2[0];}if(!finish(next)) {run= next;}if(!finish(run)) return 1;return 0;
}
当sched()选择的"下一个"线程已经finish,sched()就返回0。执行就结束了。就这些了。完整的代码贴上:
#include <stdio.h>struct vars {int a;int b;int c;int t1;int t2;
};struct vars init= {'A', 'B', 'C', 'x', 'z'};
struct vars result;struct assign {int *left;int *right;
};struct assign all_assigns[] = {{&result.t1,&result.a}, {&result.a, &result.b}, {&result.b,&result.t1},{&result.t2,&result.a}, {&result.a, &result.c}, {&result.c,&result.t2},
};void print_ins_nl(struct assign *a, int nl)
{int i;int *pi= a->left;printf("\t(%d)\t", a- &all_assigns[0]);for(i=0; i<2; i++) {if(pi==&result.a) printf("a"); elseif(pi==&result.b) printf("b"); elseif(pi==&result.c) printf("c"); elseif(pi==&result.t1) printf("t1"); elseif(pi==&result.t2) printf("t2");if(pi==a->left) {printf("=");pi=a->right;}}if(nl)printf(";\n");elseprintf(";");
}void print_ins(struct assign *a)
{print_ins_nl(a, 1);
}void print_vars(struct vars *var)
{printf("(%c, %c, %c, :%c, :%c)", var->a, var->b,var->c, var->t1, var->t2
);
}struct thread_proc {int ecount;int count;struct assign **ins;int n;int cur;
};struct assign *swap_ab_ins[3]= {&all_assigns[0], &all_assigns[1], &all_assigns[2]
};
struct assign *swap_ac_ins[3]= {&all_assigns[3], &all_assigns[4], &all_assigns[5]
};
struct thread_proc thread2[2]=
{{10, 0, swap_ab_ins, 3, 0},{10, 0, swap_ac_ins, 3, 0},
};struct thread_proc *run;
int finish(struct thread_proc *t)
{return t->count>=t->ecount;
}int sched()
{struct thread_proc *next;if(run== &thread2[0]) {next= &thread2[1];} else {next= &thread2[0];}if(!finish(next)) {run= next;}if(!finish(run)) return 1;return 0;
}void execute(struct thread_proc *t, int n)
{int i;int pos;struct assign **a;a = t->ins;if(t==&thread2[0]) {printf("swap(a,b):");}else {printf("swap(a,c):");}for(i=0; i<n; i++) {if(i) printf("\t");pos = t->cur;print_ins_nl(a[pos], 0);*(a[pos]->left) = *(a[pos]->right);printf("\t");print_vars(&result); printf("\n");t->cur++;if(t->cur>=t->n) {t->count++;t->cur=0;}if(finish(t)) break;}
}extern "C" int rand();
int random()
{return rand()%3+1;
}int main()
{int i;printf("swap(a, b):\n");for(i=0; i<3; i++) {print_ins(&all_assigns[i]);}printf("swap(a, c):\n");for(i=0; i<3; i++) {print_ins(&all_assigns[i+3]);}printf("[execute]:\n");result = init;run = &thread2[0];do {execute(run, random());}while(sched());return 0;
}
运行结果是交错执行2个线程的效果:
swap(a, b):(0) t1=a;(1) a=b;(2) b=t1;
swap(a, c):(3) t2=a;(4) a=c;(5) c=t2;
[execute]:
swap(a,b): (0) t1=a; (A, B, C, :A, :z)
swap(a,c): (3) t2=a; (A, B, C, :A, :A)(4) a=c; (C, B, C, :A, :A)(5) c=t2; (C, B, A, :A, :A)
swap(a,b): (1) a=b; (B, B, A, :A, :A)
swap(a,c): (3) t2=a; (B, B, A, :A, :B)(4) a=c; (A, B, A, :A, :B)(5) c=t2; (A, B, B, :A, :B)
swap(a,b): (2) b=t1; (A, A, B, :A, :B)(0) t1=a; (A, A, B, :A, :B)(1) a=b; (A, A, B, :A, :B)
swap(a,c): (3) t2=a; (A, A, B, :A, :A)
swap(a,b): (2) b=t1; (A, A, B, :A, :A)
swap(a,c): (4) a=c; (B, A, B, :A, :A)(5) c=t2; (B, A, A, :A, :A)
swap(a,b): (0) t1=a; (B, A, A, :B, :A)
swap(a,c): (3) t2=a; (B, A, A, :B, :B)(4) a=c; (A, A, A, :B, :B)(5) c=t2; (A, A, B, :B, :B)
swap(a,b): (1) a=b; (A, A, B, :B, :B)(2) b=t1; (A, B, B, :B, :B)
swap(a,c): (3) t2=a; (A, B, B, :B, :A)
swap(a,b): (0) t1=a; (A, B, B, :A, :A)(1) a=b; (B, B, B, :A, :A)(2) b=t1; (B, A, B, :A, :A)
swap(a,c): (4) a=c; (B, A, B, :A, :A)
swap(a,b): (0) t1=a; (B, A, B, :B, :A)(1) a=b; (A, A, B, :B, :A)(2) b=t1; (A, B, B, :B, :A)
swap(a,c): (5) c=t2; (A, B, A, :B, :A)
swap(a,b): (0) t1=a; (A, B, A, :A, :A)(1) a=b; (B, B, A, :A, :A)(2) b=t1; (B, A, A, :A, :A)
swap(a,c): (3) t2=a; (B, A, A, :A, :B)
swap(a,b): (0) t1=a; (B, A, A, :B, :B)
swap(a,c): (4) a=c; (A, A, A, :B, :B)(5) c=t2; (A, A, B, :B, :B)(3) t2=a; (A, A, B, :B, :A)
swap(a,b): (1) a=b; (A, A, B, :B, :A)(2) b=t1; (A, B, B, :B, :A)(0) t1=a; (A, B, B, :A, :A)
swap(a,c): (4) a=c; (B, B, B, :A, :A)(5) c=t2; (B, B, A, :A, :A)
swap(a,b): (1) a=b; (B, B, A, :A, :A)(2) b=t1; (B, A, A, :A, :A)(0) t1=a; (B, A, A, :B, :A)
swap(a,c): (3) t2=a; (B, A, A, :B, :B)(4) a=c; (A, A, A, :B, :B)(5) c=t2; (A, A, B, :B, :B)
swap(a,b): (1) a=b; (A, A, B, :B, :B)(2) b=t1; (A, B, B, :B, :B)(0) t1=a; (A, B, B, :A, :B)
swap(a,c): (3) t2=a; (A, B, B, :A, :A)(4) a=c; (B, B, B, :A, :A)
swap(a,b): (1) a=b; (B, B, B, :A, :A)(2) b=t1; (B, A, B, :A, :A)
swap(a,c): (5) c=t2; (B, A, A, :A, :A)
swap(a,c): (3) t2=a; (B, A, A, :A, :B)
swap(a,c): (4) a=c; (A, A, A, :A, :B)
swap(a,c): (5) c=t2; (A, A, B, :A, :B)