信号量与临界资源的使用——双向道路汽车过窄桥

来源:互联网 发布:金仕达交易软件 官网 编辑:程序博客网 时间:2024/04/29 00:16

         临界资源或临界区是指在同一时刻只允许一个进程或线程访问,并且只有当占有该资源的进程释放了该资源后,才能被其他进程使用。因此需要设计一种机制保障进程间的通信,使得不同的进程能够知道临界资源的使用情况,当某个进程占据了临界资源时,应该告知其他进程该资源已经被占用,避免其他进程错误的访问和使用临界资源。信号量即是一种进程间通信的方法,它使用一个整形变量来累计唤醒次数,供以后使用,当信号量只有两种状态时,表示该资源只能被唤醒一次或者占用一次,此时对临界资源的访问就是互斥的。

       在这里我设计了一个多线程编程的小程序,通过动画的形式展示出来上述调度过程。设计了一个双向单车道的道路上中间有一个窄桥,一次只允许一辆车通过。因此不同方向的来车在通过窄桥时候应该首先判断桥是否为空,只有为空的情况下才能通过,并且当占有桥时候,还要告诉其他车辆该桥已经有车通过。因此在程序中设置了一个表示临界资源——桥的信号量bridgeMutex,初始化为0,当有车占有桥时候,即将信号量设置为1,其他要上桥的车辆即被阻塞,当车辆通过桥后,就唤醒信号量bridgeMutex,重新设置为0.此时其他车辆就可以访问桥了。在这个程序中每一个车辆是一个线程。测试的时候生成了两个车辆,也就是两个线程,当两个车辆行驶到桥的时候,会发现其中一个车辆会等另外一个车辆先通过后,自己再通过。先通过的车辆即抢先占据临界资源的车辆。

        程序是采用C语言编程的,建立的是.cpp文件,需要配置多线程编程的环境,采用的是POSIX线程标准的Pthread. 另外为了通过动画演示,配置了一个easyx图形库的环境。

C程序源代码如下:

#include <pthread.h>
#include <iostream>
#include "easyx.h"
#include <graphics.h> 
#include "time.h"
#pragma comment(lib, "pthreadVC2.lib")
int bridgeMutex=0;
int rightEnd=617,leftEnd=1;
int moveStep=22,goRight=295,goLeft=320,onBridge=307;
int leftRodeUp[12],leftRodeDown[12],rightRodeUp[12],rightRodeDown[12],bridge[5];


void* carGoRight(void* args);
void* carGoLeft(void* args);


int drawGoRight(int i,int j);
int drawGoLeft(int i,int j);
int drawRode();


int main(){
pthread_t goRight[10];
pthread_t goLeft[10];
int i=0;
initgraph(640,640);
for (i=0;i<12;i++)
{
leftRodeUp[i]=0;
leftRodeDown[i]=0;
rightRodeUp[i]=0;
rightRodeDown[i]=0;
if(i<5)
{
bridge[i]=0;
}
}
drawRode();
for(i=0;i<1;i++)
{
pthread_create(&goRight[i],NULL,carGoRight,NULL);
pthread_create(&goLeft[i],NULL,carGoLeft,NULL);
pthread_join(goRight[i],NULL);
pthread_join(goLeft[i],NULL);
}
Sleep(2000);
return 0;
}




void* carGoRight(void* args)
{
       int i=1,j=295,k=0;
       while(i<=rightEnd)
  {
  k=(i-1)/moveStep;
  if (k<12)
  {
  while (leftRodeUp[k]==1)
  {
  Sleep(100);
  }
  leftRodeUp[k]=1;
  if (k>0)
  {
  leftRodeUp[k-1]=0;
  clearrectangle(i-22,j+4,i,j+5+19); //清除原来位置的车
  }
  drawGoRight(i+1,j+5);


  i += 22;


  }
  else if (k==12) //等待上桥
  {
  while (bridgeMutex==1)
  {
  Sleep(100);
  }
  bridgeMutex=1; //占有临界区——窄桥
  bridge[k-12]=1;
  leftRodeUp[k-1]=0;
  clearrectangle(i-22,j+4,i,j+5+19);


  drawGoRight(i+1,j+5+12);
  i += 22;
  }
  else if(k<17)
  {
  bridge[k-12]=1;
  bridge[k-12-1]=0;
  clearrectangle(i-22,j+4+12,i,j+5+19+12);
  drawGoRight(i+1,j+5+12);
  i += 22;
  }
  else if (k==17) //进入右边道路,释放桥
  {
  while (rightRodeUp[k-17]==1)
  {
  Sleep(100);
  }
  rightRodeUp[k-17]=1;
  bridge[k-12-1]=0;
  bridgeMutex=0;
  clearrectangle(i-22,j+4+12,i,j+5+19+12);
  drawGoRight(i+1,j+5);
  i += 22;
  }
  else if (k<29)//在右边道路上
  {
  while (rightRodeUp[k-17]==1)
  {
  Sleep(100);
  }
  rightRodeUp[k-17]=1;
  rightRodeUp[k-17-1]=0;
  clearrectangle(i-22,j+4,i,j+5+19);
  drawGoRight(i+1,j+5);
  i += 22;
  }
  Sleep(300);
       }
  rightRodeUp[11]=0;
       clearrectangle(i-22,j+4,i,j+5+19);
       return NULL;
}


void* carGoLeft(void* args)
{
int i=rightEnd,j=320,k=0;
while(i>=leftEnd)
{
k=(rightEnd-i)/moveStep;
if (k<12)   //在左边道路上
{
while (rightRodeDown[11-k]==1)
{
Sleep(100);
}
rightRodeDown[11-k]=1;
if (k>0)
{
rightRodeDown[11-k+1]=0;
clearrectangle(i+22,j+4,i+44,j+5+19); //清除原来位置的车
}
drawGoLeft(i+1,j+5);

i -= 22;

}
else if (k==12) //等待上桥
{
while (bridgeMutex==1)
{
Sleep(100);
}
bridgeMutex=1; //占有临界区——窄桥
bridge[16-k]=1;
rightRodeDown[11-k+1]=0;
clearrectangle(i+22,j+4,i+44,j+5+19);

drawGoLeft(i+1,j+5+12-25);
i -= 22;
}
else if(k<17)
{
bridge[16-k]=1;
bridge[16-k+1]=0;
clearrectangle(i+22,j+4+12-25,i+44,j+5+19+12-25);
drawGoLeft(i+1,j+5+12-25);
i -= 22;
}
else if (k==17) //进入左边道路,释放桥
{
while (leftRodeDown[28-k]==1)
{
Sleep(100);
}
leftRodeDown[28-k]=1;
bridge[17-k]=0;
bridgeMutex=0;
clearrectangle(i+22,j+4+12-25,i+44,j+5+19+12-25);
drawGoLeft(i+1,j+5);
i -= 22;
}
else if (k<29)//在左边道路上
{
while (leftRodeDown[28-k]==1)
{
Sleep(100);
}
leftRodeDown[28-k]=1;
leftRodeDown[28-k+1]=0;
clearrectangle(i+22,j+4,i+44,j+5+19);
drawGoLeft(i+1,j+5);
i -= 22;
}
Sleep(300);
}
leftRodeDown[0]=0;
clearrectangle(1,j+4,1+22,j+5+19);
return NULL;
}


int drawGoRight(int i,int j)
{
rectangle(i,j,i+20,j+15);
solidcircle(i+5,j+15,3);
solidcircle(i+15,j+15,3);
line(i+7,j+5,i+13,j+5);
line(i+13,j+5,i+11,j+3);
line(i+13,j+5,i+11,j+8);
return 1;
}
int drawGoLeft(int i,int j)
{
rectangle(i,j,i+20,j+15);
solidcircle(i+5,j+15,3);
solidcircle(i+15,j+15,3);


line(i+7,j+5,i+13,j+5);
line(i+7,j+5,i+9,j+3);
line(i+7,j+5,i+9,j+8);
return 1;
}
int drawRode()
{
//clearrectangle(i-1,j-1,i+21,j+19);
line(0,295,265,295);//left rode
line(0,345,265,345);
line(0,320,265,320);


line(265,307,265,295);
line(265,333,265,345);


line(265,307,375,307);//bridge
line(265,333,375,333);


line(375,295,640,295);//right rode
line(375,345,640,345);
line(375,320,640,320);


line(375,295,375,307);
line(375,345,375,333);


return 1;
}

程序运行结果;






0 0
原创粉丝点击