2015-12-08 71 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)循環內忙於等待。