2015-12-08 30 views
0

所以我模拟了一个有四个队列(每个方向)和一个全局交集Q的汽车交叉口。程序运行良好,没有使用usleep注释掉)。但是当我使用睡觉时,没有任何反应。在线程中添加usleep()后,程序被禁止(无输出)

我确定它是因为被推入globalQ的localID不同于在本地(定向)队列中被推入的localID。 (localID == northQ.front()) &(localID == globalQ.front()))“ 永远不会满足。

原因我在介绍“usleep(getrand(100000,3000000));”是因为我想为赛车的速度添加一些随机性。我知道这可能有点混乱。但重点是程序运行时没有睡眠命令。但是当我介绍它时,没有任何反应......我猜想有些饥饿。

编辑:主要4个功能是相同的东西。只是不同的队列名称。

EDIT2:如果我睡了一定的时间,程序就能正常工作。如果那个时间是我指定的某个时间间隔的随机数,它就不起作用。

代码:

// Instructions 
// Change the CARS and RUN_TIME variable to the desired values. 
// Compile in command line using: g++ -pthread Intelligent_Traffic_Light_System.cpp -o run.exe 
// Run in command line by using: ./run.exe 

#include <iostream> 
#include <pthread.h> 
#include <queue> 
#include <cstdlib> //for rand() 
#include <unistd.h> // for usleep() 
#include <ctime> //for clock(), clock_t, CLOCKS_PER_SEC 

#define CARS 10 // # cars coming from each direction. 40 cars total 
#define RUN_TIME 125 // 125 seconds (5 seconds longer than it should take to run) 

using namespace std; 

int globalID; // global ID for each car arriving at the intersection 

// a queue for each direction. 
queue<int> northQ; 
queue<int> eastQ; 
queue<int> southQ; 
queue<int> westQ; 
queue<int> globalQ; 

pthread_t threadID; 

// a lock for each queue/direction. 
pthread_mutex_t northLock; 
pthread_mutex_t eastLock; 
pthread_mutex_t southLock; 
pthread_mutex_t westLock; 
pthread_mutex_t globalQlock; 

pthread_mutex_t globalIDLock; // lock for changing the globalid (i.e. car id) 
pthread_mutex_t intersectionLock; // lock for one car passing through the intersection 


int getrand(int min,int max) //random number generator between min and max 
{ 
     return(rand()%(max-min)+min); 
} 


void init() 
{ 
    globalID = 1; //first car will have ID = 1 
    pthread_mutex_init(&northLock, NULL); 
    pthread_mutex_init(&eastLock, NULL); 
    pthread_mutex_init(&southLock, NULL); 
    pthread_mutex_init(&westLock, NULL); 
    pthread_mutex_init(&globalIDLock, NULL); 
    pthread_mutex_init(&intersectionLock, NULL); 
    pthread_mutex_init(&globalQlock, NULL); 
} 

// Now will test to create an intersection with only 1 direction. North 
void *north(void *null) 
{ 

    int localID; 
    double duration; //for checking how long a car will be waiting at the front of its lane 
    clock_t start; //variable will be used to calculate wait time 

    pthread_mutex_lock(&northLock); // locking the queue 
    pthread_mutex_lock(&globalIDLock); // locking globalIDLock mutex in order to update globalID 
    localID = globalID++; // update globalID after reserving that ID for a car in north lane 
    pthread_mutex_unlock(&globalIDLock); 
    northQ.push(localID); // pushing the local car into northQ. 
    pthread_mutex_unlock(&northLock); 

    //usleep(getrand(100000, 3000000)); //lets say it takes somewhere between 1/10th of a second and 3 seconds to get to the intersection. 
    start = clock(); // Now the car has arrived at intersection. Let's start the timer. 

    pthread_mutex_lock(&globalQlock); 
    globalQ.push(localID);//pushing car into global (intersection Q) 
    //cout << localID <<endl; 
    pthread_mutex_unlock(&globalQlock); 

    while(1) //Checking cars properties here 
    { 
     if ((localID == northQ.front()) && (localID == globalQ.front())) // Current Car is in the front of the lane... Lets Proceed 
     { 
      break; 
     } 
     else //Current car is not in front on its lane. Lets wait 
     { 
      usleep(10); // sleep for 10 microsecond to allow for other cars to proceed if they must 
      continue; 
     } 
    } 

    // Car is in the front so let's proceed to allow it to pass through intersection. 
    pthread_mutex_lock(&intersectionLock); // need to lock the intersection. Function call will block until mutex is available 
    duration = (std::clock() - start)/(double) CLOCKS_PER_SEC; 
    northQ.pop(); 
    globalQ.pop(); 
    cout << "Car from NORTH lane with ID: " << localID << " ENTERING the intersection." << endl; 
    cout << "It has been waiting at the light for: "<< duration<<" seconds."<<endl; 
    sleep(3); 
    cout << "Car from NORTH lane with ID: " << localID << " LEAVING the intersection." << endl<<endl; 
    pthread_mutex_unlock(&intersectionLock); // give other cars a chance to pass 
} 


void *east(void *null) 
{ 

    int localID; 
    double duration; 
    clock_t start; 

    pthread_mutex_lock(&eastLock); // locking the queue 
    pthread_mutex_lock(&globalIDLock); // locking globalIDLock mutex in order to update globalID 
    localID = globalID++; // update globalID after reserving that ID for a car in north lane 
    pthread_mutex_unlock(&globalIDLock); 
    eastQ.push(localID); // pushing the local car into northQ. 
    pthread_mutex_unlock(&eastLock); 

    //usleep(getrand(100000, 3000000)); //lets say it take 1/10th of a second to get to the intersection. 
    start = clock(); 

    pthread_mutex_lock(&globalQlock); 
    globalQ.push(localID);//pushing car into global queue (i.e. intersection queue) 
    pthread_mutex_unlock(&globalQlock); 


    while(1) //Checking cars properties here 
    { 
     if ((localID == eastQ.front()) && (localID == globalQ.front())) // Current Car is in the front of the lane... Lets Proceed 
     { 
      break; 
     } 
     else //Current car is not in front on its lane. Lets wait 
     { 
      usleep(10); // sleep for 10 microsecond to allow for other cars to proceed if they must 
      continue; 
     } 
    } 

    // Car is in the front so let's proceed to allow it to pass through intersection. 
    pthread_mutex_lock(&intersectionLock); // need to lock the intersection. Function call will block until mutex is available 
    duration = (std::clock() - start)/(double) CLOCKS_PER_SEC; 
    eastQ.pop(); 
    globalQ.pop(); 

    cout << "Car from EAST lane with ID: " << localID << " ENTERING the intersection." << endl; 
    cout << "It has been waiting at the light for: "<<duration<<" seconds."<<endl; 
    sleep(3); 
    cout << "Car from EAST lane with ID: " << localID << " LEAVING the intersection." << endl <<endl; 
    pthread_mutex_unlock(&intersectionLock); // give other cars a chance to pass 
} 


void *south(void *null) 
{ 

    int localID; 
    double duration; 
    clock_t start; 

    pthread_mutex_lock (&southLock); // locking the queue 
    pthread_mutex_lock (&globalIDLock); // locking globalIDLock mutex in order to update globalID 
    localID = globalID++; // update globalID after reserving that ID for a car in north lane 
    pthread_mutex_unlock (&globalIDLock); 
    southQ.push(localID); // pushing the local car into northQ. 
    pthread_mutex_unlock (&southLock); 

    //usleep(getrand(100000, 3000000)); //lets say it take 1/10th of a second to get to the intersection. 
    start = clock(); 

    pthread_mutex_lock(&globalQlock); 
    globalQ.push(localID);//pushing car into global (intersection Q) 
    pthread_mutex_unlock(&globalQlock); 


    while(1) //Checking cars properties here 
    { 
     if ((localID == southQ.front()) && (localID == globalQ.front())) // Current Car is in the front of the lane... Lets Proceed 
     { 
      break; 
     } 
     else //Current car is not in front on its lane. Lets wait 
     { 
      usleep(10); // sleep for 10 microsecond to allow for other cars to proceed if they must 
      continue; 
     } 

    } 

    // Car is in the front so let's proceed to allow it to pass through intersection. 
    pthread_mutex_lock(&intersectionLock); // need to lock the intersection. Function call will block until mutex is available 
    duration = (std::clock() - start)/(double) CLOCKS_PER_SEC; 
    southQ.pop(); 
    globalQ.pop(); 

    cout << "Car from SOUTH lane with ID: " << localID << " ENTERING the intersection." << endl; 
    cout << "It has been waiting at the light for: "<<duration<< " seconds."<<endl; 
    sleep(3); 
    cout << "Car from SOUTH lane with ID: " << localID << " LEAVING the intersection." << endl<<endl; 
    pthread_mutex_unlock(&intersectionLock); // give other cars a chance to pass 
} 


void *west(void *null) 
{ 

    int localID; 
    double duration; 
    clock_t start; 

    pthread_mutex_lock (&westLock); // locking the queue 
    pthread_mutex_lock (&globalIDLock); // locking globalIDLock mutex in order to update globalID 
    localID = globalID++; // update globalID after reserving that ID for a car in north lane 
    pthread_mutex_unlock (&globalIDLock); 
    westQ.push(localID); // pushing the local car into northQ. 
    pthread_mutex_unlock (&westLock); 

    //usleep(getrand(100000, 3000000)); 
    start = clock(); 

    pthread_mutex_lock(&globalQlock); 
    globalQ.push(localID);//pushing car into global (intersection Q) 
    pthread_mutex_unlock(&globalQlock); 



    while(1) //Checking cars properties here 
    { 
     if ((localID == westQ.front()) && (localID == globalQ.front())) // Current Car is in the front of the lane... Lets Proceed 
     { 
      break; 
     } 
     else //Current car is not in front on its lane. Lets wait 
     { 
      usleep(10); // sleep for 10 microsecond to allow for other cars to proceed if they must 
      continue; 
     } 

    } 

    // Car is in the front so let's proceed to allow it to pass through intersection. 
    pthread_mutex_lock(&intersectionLock); // need to lock the intersection. Function call will block until mutex is available 
    duration = (std::clock() - start)/(double) CLOCKS_PER_SEC; 
    westQ.pop(); 
    globalQ.pop(); 
    cout << "Car from WEST lane with ID: " << localID << " ENTERING the intersection." << endl; 
    cout << "It has been waiting for: "<< duration <<" seconds."<< endl; 
    sleep(3); 
    cout << "Car from WEST lane with ID: " << localID << " LEAVING the intersection." << endl<<endl; 
    pthread_mutex_unlock(&intersectionLock); // give other cars a chance to pass 
} 


int main() 
{ 
    init(); 

    for(int i = 0; i < CARS; i++) //first car will be car with ID 1; Last ID is 40 
    { 
     pthread_create (&threadID, NULL, north, NULL); 
     pthread_create (&threadID, NULL, east, NULL); 
     pthread_create (&threadID, NULL, south, NULL); 
     pthread_create (&threadID, NULL, west, NULL); 
    } 
    sleep(RUN_TIME); //sleep for sufficient times to allow for all threads to finish running. 

    cout << "Finished." << endl; 

    return 0; 
} 
+1

这是真的** [最小工作示例](http://stackoverflow.com/help/mcve)**? –

+0

[useconds参数应小于一百万。如果useconds的值为0,则调用不起作用。](http://pubs.opengroup.org/onlinepubs/009695399/functions/usleep.html) – POTEMKINDX

回答

0

看来,之前主线程退出“北” - “东方”等线程终止:

  1. 当我把sleep(RUN_TIME)主循环里面,该程序开始工作。
  2. 提前终止的原因是(localID == globalQ.front())位于每个“北” - “东”功能内的非同步代码。正如你已经正确提到的那样,这个代码从来没有(几乎)满意,并且导致在while(1)循环内忙于等待。