经典互斥有关问题模拟-单车道过桥-模拟代码
经典互斥问题模拟--单车道过桥--模拟代码
实习作业:多线程基础编程实践
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] <-