【解释】代码中黑色的部分为为保证公平性的代码,补充红色部分就实现了公平性。
【思路】首先,原来的算法,如果有两个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