【解释】代码中黑色的部分为为保证公平性的代码,补充红色部分就实现了公平性。 【思路】首先,原来的算法,如果有两个THREAD的都申请想要进入临界区,此时他们的 lock=1;这样当一个THREAD运行完临界区代码后,直接就退出了,而另外一个lock还是 1时就会因为test_and_set只能让lock=0的THREAD进入临界区这一原因而使得它阻塞, 陷入无线等待时间。 【更改】为算法补充标志数组wait[],这样一来,如果两个THREAD都有想进去的意愿时,THREAD 0 把lock置为1,wait[0]置为1,进入临界区后,在ExitControl(int i)中,判断是 否还有另一THREAD i把lock置为1,是的话就将lock置为0开放临界区,不是的话就将 wait[0]置为0。 【代码】 #include <sched.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #define THREADS 8 volatile int mutex=0; volatile int wait[THREADS]; //设置标志数组 int sharedvar=0; void EnterControl(int i) //THREAD进入部分 { int lock=1; //此时表示该THREAD还未进入临界区,依旧允许其他THREAD进入 wait[i]=1; //表示准备进入临界区 while(wait[i] && __sync_lock_test_and_set(&mutex,lock)) continue; //将lock的值赋给mutex,如果满足条件并且wait[i]=1就结束循环就进入临界区 wait[i]=0; //THREAD进入后让等待的置零 printf("No%d entered the CR(%d#)\n",i,getpid()); } void ExitControl(int i) //THREAD退出部分 { int j; j=(i+1) % THREADS; //j表示运行的THREAD while(j!=i && !wait[j]) //如果j进程不是i THREAD,并且该进程并未准备进入临界区 j=((j+1) % THREADS); //j往后 if(j==i) //如果有THREAD的lock,就让他的lock置0,进入临界区 __sync_lock_release(&mutex); //mutex=0,开放临界区 else //如果不是的话,回到等待态等待其他THREAD进入 wait[j]=0; printf("\t\tNo%d quit the CR(%d#)\n",i,getpid()); } int AccessSharedV(void *args) { int id=*((int *)args); int i; for(i=0;i<10;i++){ if(i<4) sleep(id+1); else sleep(i); EnterControl(id); //临界区开始 sharedvar=sharedvar+id+1; printf("\tsharedvar=%d,thread id=%d\n",sharedvar,getpid()); //临界区结束 ExitControl(id); } } main() { int i,clone_flag,arg,retval; char *stack; clone_flag=CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES; for(i=0;i<THREADS;i++){ wait[i]=0; //让所有THREAD初始都不没有想要进入的临界区的意愿 arg=i; stack=(char *)malloc(4096); retval=clone((void *)AccessSharedV,&(stack[4095]),clone_flag,(void*)&arg); } exit(0); }
Leave Your Comment Here