经典互斥问题模拟--单车道过桥--模拟代码

实习作业:多线程基础编程实践


pass_bridge.cpp


/*
* 	compile: g++ -o pass_bridge.out pass_bridge.cpp -lpthread
* 	run: ./pass_bridge.out
*	this programe should run on a linux OS 
*
*
*
*/ 

//head files 
#include <sys/socket.h>  
#include <sys/types.h>  
#include <poll.h>               
#include <unistd.h>          
#include <netdb.h>           
#include <error.h>           
#include <stdlib.h>  
#include <time.h>  
#include <stdio.h>  
#include <errno.h>  
#include <string.h>  
#include <netdb.h>  
#include <netinet/in.h>  
#include <arpa/inet.h> 
#include <pthread.h> 
#include <list> 
#include <iterator> 
#include <algorithm> 
#include "randutil.h"
#include "car.h"

//init param
pthread_mutex_t mutex1; //use when changing count1
pthread_mutex_t mutex2; //use when changing count2
pthread_mutex_t output; //use when the programe needs output
int count1 = 0; //the number of cars waiting on the leftside to pass through the bridge
int count2 = 0; // cars waiting on the right side ...
/*  
*	-1 stands for no cars requests for passing
*	Car::LEFT_TO_RIGHT means cars waiting on the left side got the chance to passing through 
*	Car::RIGHT_TO_LEFT means cars waiting on the right side got the chance to passing through
*/ 
int state=-1; 
std::list<Car *> cars;

//configure info
int pass_sleep_time_width = 3;
int car_join_sleep_time_width = 3;
#define NUM_CARS 20 //number of cars 
int car_seq_width = 3;
Car arr_cars[NUM_CARS];

//comparator 
bool CompareRules(Car* x,  Car* y)
{
	if(x->sq < y->sq)
		return true;
	else
		return false;
}

//show the state of the bridge 
void show_state()
{
	//printf("state = %d\n",state);
	
	cars.sort(CompareRules); 
	std::list<Car *>::iterator it=cars.begin();
	for(;it!=cars.end();it++)
	{
		if((*it)->state == Car::WAIT && (*it)->dir == Car::LEFT_TO_RIGHT)
			printf("[%d] ",(*it)->id);
	}
	
	if(state == Car::LEFT_TO_RIGHT)
		printf(" -> ");
	else if(state == Car::RIGHT_TO_LEFT)
		printf(" <- ");
	
	if(state == -1)
		printf(" -- ---- --");
	else
	{
		it=cars.begin();
		for(;it!=cars.end();it++)
		{
			if((*it)->state == Car::PASSING)
				printf("[%d] ",(*it)->id);
		}	
	}
	
	if(state == Car::LEFT_TO_RIGHT)
		printf(" -> ");
	else if(state == Car::RIGHT_TO_LEFT)
		printf(" <- ");
		
	it=cars.begin();
	for(;it!=cars.end();it++)
	{
		if((*it)->state == Car::WAIT && (*it)->dir == Car::RIGHT_TO_LEFT)
			printf("[%d] ",(*it)->id);
	}
	
	puts("");
}


void *left_to_right(void * arg)
{
     Car * c = &arr_cars[*((int *)arg)];
     
     pthread_mutex_lock(&output);
     c->pass();
     c->state=Car::WAIT;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_lock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     //P(S1)
     pthread_mutex_lock(&mutex1);
    
     //IF(COUNT1==0)
     if(count1==0){
     		//P(S2)
            pthread_mutex_lock(&mutex2);
            state = Car::LEFT_TO_RIGHT;
     }
    //COUNT1++
     count1++;
     //V(S1)
     pthread_mutex_unlock(&mutex1);
     //PASSING THROUGH
     pthread_mutex_lock(&output);
     c->passing();
     c->state=Car::PASSING;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_lock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     usleep(RANDOM::getNumber(pass_sleep_time_width));
     
     //P(S1)
     pthread_mutex_lock(&mutex1);
     //COUNT1--
     count1--;
     //IF(COUNT1==0)
     if(count1==0){
     		//V(S2)
            pthread_mutex_unlock(&mutex2);
            state = -1;
     }
     //V(S1)
     pthread_mutex_unlock(&mutex1);
     
     pthread_mutex_lock(&output);
     c->passed();
     c->state=Car::PASSED;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_lock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     pthread_exit(0);
}

void *right_to_left(void * arg)
{
     Car * c = &arr_cars[*((int *)arg)];
     pthread_mutex_lock(&output);
     c->pass();
     c->state=Car::WAIT;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_lock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     //P(S2)
     pthread_mutex_lock(&mutex2);
     //IF(COUNT2==0)
     if(count2==0){
     		//P(S1)
            pthread_mutex_lock(&mutex1);
            state = Car::RIGHT_TO_LEFT;
     }
     //COUNT2++
     count2++;
     //V(S2)
     pthread_mutex_unlock(&mutex2);
     //PASSING THROUGH
     
     pthread_mutex_lock(&output);
     c->passing();
     c->state=Car::PASSING;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_lock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     usleep(RANDOM::getNumber(pass_sleep_time_width));
     
     //P(S2)
     pthread_mutex_lock(&mutex2);
     //COUNT2--
     count2--;
     //IF(COUNT2==0)
     if(count2==0){
     		//V(S1)
            pthread_mutex_unlock(&mutex1);
            state = -1;
     }
     //V(S2)
     pthread_mutex_unlock(&mutex2);
     
     pthread_mutex_lock(&output);
     c->passed();
     c->state=Car::PASSED;
     pthread_mutex_unlock(&output);
	 
     pthread_mutex_unlock(&output);
     show_state();
     pthread_mutex_unlock(&output);
     pthread_exit(0);
}


int main()
{
    
    pthread_t tid1,tid2;
    int num=0;
    for(int i=0;i<NUM_CARS;i++)
    {
    	arr_cars[i].id = RANDOM::getNumber(car_seq_width);
    	arr_cars[i].sq = ++num;
		cars.push_back(&arr_cars[i]);
    }
    std::list<Car *>::iterator it=cars.begin();
    int num_cars = NUM_CARS;
    num = 0;
    while(num_cars--){
             int who = RANDOM::getNumber(2);
             if(who%2==0){
					(*it)->dir = Car::LEFT_TO_RIGHT;
					pthread_create(&tid1,NULL,left_to_right,&num);  
             }
             else
             {
					(*it)->dir = Car::RIGHT_TO_LEFT;
					pthread_create(&tid2,NULL,right_to_left,&num);  
             }
             usleep(RANDOM::getNumber(car_join_sleep_time_width));
             num++;
             it++;
    }
    return 0;
    
}



car.h


#include <stdio.h>
 
class Car{
      
public:
       static const int LEFT_TO_RIGHT = 0;
       static const int RIGHT_TO_LEFT = 1;
       
       static const int OUT = 0;
       static const int WAIT = 1;
       static const int PASSING = 2;
       static const int PASSED = 3;
       
       int dir; 
       int id;
       int sq;
       int state;
       
       Car(){}
       
       Car(int id,int dir,int num)
       {
            sq = num;
            this->id=id;
            this->dir=dir;
            state = Car::OUT;
       }
       
       Car(int id,int num)
       {
            sq = num;
            this->id=id;
            state = Car::OUT;
       }
             
       void pass()
       {
            if(dir==Car::LEFT_TO_RIGHT)
            {
                   printf(">-- :car %d requests for passing\n",this->id);               
            }
            else
            {
                   printf("--< :car %d requests for passing\n",this->id);
            }
       }
       
       void passing()
       {
            if(dir==Car::LEFT_TO_RIGHT)
            {
                   printf("->- :car %d is passing\n",this->id);               
            }
            else
            {
                   printf("-<- :car %d is passing\n",this->id);
            }
       }
       
       void passed()
       {
            if(dir==Car::LEFT_TO_RIGHT)
            {
                   printf("--> :car %d has passed\n",this->id);               
            }
            else
            {
                   printf("<-- :car %d has passed\n",this->id);
            }
       }
       
};




randutil.h


#include <stdlib.h>  
#include <time.h>  
  
class RANDOM   
{  
        public:  
               //width stands for its width   
                static long getNumber(int width)  
                {  
  
                        width--;  
                        long ret=0;  
                        ret = rand()%9+1;  
                        long range=1;  
                        while(width--)  
                        {  
                                ret*=10;  
                                range*=10;  
                        }  
                        return ret+rand()%range;  
  
                }  
};  



运行结果:


[root@bogon mutex]# g++ -o pass_bridge.out pass_bridge.cpp -lpthread
[root@bogon mutex]# ./pass_bridge.out 
--< :car 286 requests for passing
 -- ---- --[286] 
-<- :car 286 is passing
 <- [286]  <- 
<-- :car 286 has passed
 -- ---- --
>-- :car 115 requests for passing
[115]  -- ---- --
->- :car 115 is passing
 -> [115]  -> 
--> :car 115 has passed
 -- ---- --
>-- :car 635 requests for passing
[635]  -- ---- --
->- :car 635 is passing
 -> [635]  -> 
--> :car 635 has passed
 -- ---- --
--< :car 292 requests for passing
 -- ---- --[292] 
-<- :car 292 is passing
 <- [292]  <- 
<-- :car 292 has passed
 -- ---- --
--< :car 721 requests for passing
 -- ---- --[721] 
-<- :car 721 is passing
 <- [721]  <- 
<-- :car 721 has passed
 -- ---- --
--< :car 627 requests for passing
 -- ---- --[627] 
-<- :car 627 is passing
 <- [627]  <- 
<-- :car 627 has passed
 -- ---- --
>-- :car 659 requests for passing
[659]  -- ---- --
->- :car 659 is passing
 -> [659]  -> 
>-- :car 626 requests for passing
[626]  -> [659]  -> 
->- :car 626 is passing
 -> [659] [626]  -> 
--> :car 659 has passed
 -> [626]  -> 
--> :car 626 has passed
 -- ---- --
--< :car 726 requests for passing
 -- ---- --[726] 
-<- :car 726 is passing
 <- [726]  <- 
<-- :car 726 has passed
 -- ---- --
>-- :car 836 requests for passing
[836]  -- ---- --
->- :car 836 is passing
 -> [836]  -> 
--> :car 836 has passed
 -- ---- --
>-- :car 968 requests for passing
[968]  -- ---- --
->- :car 968 is passing
 -> [968]  -> 
>-- :car 729 requests for passing
[729]  -> [968]  -> 
->- :car 729 is passing
 -> [968] [729]  -> 
--> :car 968 has passed
 -> [729]  -> 
>-- :car 930 requests for passing
[930]  -- ---- --
->- :car 930 is passing
 -> [729] [930]  -> 
--> :car 729 has passed
 -> [930]  -> 
--> :car 930 has passed
 -- ---- --
--< :car 923 requests for passing
 -- ---- --[923] 
-<- :car 923 is passing
 <- [923]  <- 
<-- :car 923 has passed
 -- ---- --
--< :car 235 requests for passing
 -- ---- --[235] 
-<- :car 235 is passing
 <- [235]  <- 
>-- :car 602 requests for passing
[602]  <- [235]  <- 
<-- :car 235 has passed
[602]  -- ---- --
->- :car 602 is passing
 -> [602]  -> 
--> :car 602 has passed
 -- ---- --
--< :car 158 requests for passing
 -- ---- --[158] 
-<- :car 158 is passing
 <- [158]  <- 
<-- :car 158 has passed
 -- ---- --
--< :car 667 requests for passing
 -- ---- --[667] 
-<- :car 667 is passing
 <- [667]  <- 
<-- :car 667 has passed
 -- ---- --
--< :car 256 requests for passing
 -- ---- --[256] 
-<- :car 256 is passing
 <- [256]  <- 
--< :car 542 requests for passing
 -- ---- --[542] 
-<- :car 542 is passing
 <- [256] [542]  <- 
<-- :car 256 has passed
 <- [542]  <- 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值