在线程中添加usleep()后程序缺乏(无输出)

时间:2015-12-08 08:18:58

标签: c++ multithreading pthreads

所以我模拟了一个汽车十字路口,有四个队列(每个方向)和一个全局交叉点Q.程序运行良好,没有usleep(注释掉)。但是当我使用usleep时,没有任何反应。

我确定它是因为推入globalQ的localID与在本地(方向)队列中推送的localID不同。 所以这行“if((localID == northQ.front())&&(localID == globalQ.front()))” 永远不会满足。

我正在介绍“usleep(getrand(100000,3000000));”是因为我想为汽车的速度添加一些随机性。我知道这可能有点令人困惑。但重点是程序在没有sleep命令的情况下运行。但是当我介绍它时,没有任何反应......我想有些饥饿。

编辑:主要的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 个答案:

答案 0 :(得分:0)

似乎主要线程在&#34; north&#34; - &#34; east&#34;之前退出。等线程终止:

  1. 当我将sleep(RUN_TIME)放入主循环时,程序开始工作。
  2. 提前终止的原因是(localID == globalQ.front())未同步的代码位于每个&#34; north&#34; - &#34; east&#34;功能。正如您所正确提到的,此代码永远不会(几乎)满足并导致在while(1)循环内忙等待。