实习作业:多线程基础编程实践
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] <-
经典互斥问题模拟--单车道过桥--模拟代码,布布扣,bubuko.com
原文:http://blog.csdn.net/jack_wong2010/article/details/21519817