使用std :: thread的C ++多线程应用程序在Windows上运行正常,但不适用于Ubuntu

时间:2015-12-11 20:47:42

标签: c++ windows multithreading c++11 ubuntu

我有一个简单的多线程应用程序,使用C ++ std :: thread库为Ubuntu 14.04和Windows 8.1编写。代码几乎完全相同,只是我使用操作系统各自的库windows.h和unistd.h来使用Sleep / sleep暂停执行一段时间。它们实际上都开始运行,Ubuntu版本确实会继续运行一段时间,但随后会挂起。我正在使用睡眠/睡眠功能的正确参数,因为我知道Windows Sleep需要几毫秒,而Unix睡眠需要几秒钟。

我已经多次运行代码,在Ubuntu上它永远不会超过两分钟,而我已经在Windows上运行了两次20分钟,然后多次运行大约五分钟,看看我是不是很幸运这只是与线程库的不兼容,还是睡眠不能做我认为它做的事情,或其他什么?无限循环就在那里,因为这是一个学校项目,预计会在没有死锁或崩溃的情况下运行。

要点是,这是一个经过修改的4路站点,首先到达的车辆不必放慢速度并停下来。我们只需要让一辆车穿过十字路口,需要3秒才能穿过,因此睡觉(3000),不必担心转弯。三个线程运行spawnCars函数,还有四个其他线程,每个线程监视N,E,S和W四个方向中的一个。我希望我可以理解为什么我不能发布整个代码其他学生偶然发现这个机会。这两个函数是 only ,其中代码与顶部的操作系统相关库包含不同。感谢。

编辑:由于我刚刚离开并发布了该项目的所有代码,如果问题最终导致死锁,我可以请求您只是这样说,而不是发布深入解决方案吗?我是新来的,所以如果这违背了SO的精神那么就会消失,我会在没有阅读细节的情况下试图弄明白。

        /* function clearIntersection
        Makes a car go through the intersection.  The sleep comes before the removal from the queue
        because my understanding is that the wait condition simulates the go signal for drivers.
        It wouldn't make sense for the sensors to tell a car to go if the intersection isn't yet
        clear even if the lock here would prevent that.
        */
        void clearIntersection(int direction)
        {
            lock->lock();
            Sleep(3000);
            dequeue(direction);
            lock->unlock();
        }
        /* function atFront(int direction)
        Checks whether the car waiting at the intersection from a particular direction
        has permission to pass, meaning it is at the front of the list of ALL waiting cars.
        This is the waiting condition.
        */
        bool isAtFront(int direction)
        {
            lock->lock();
            bool isAtFront = cardinalDirections[direction].front() == list->front();
            lock->unlock();
            return isAtFront;
        }


        void waitInLine()
        {
            unique_lock<mutex> conditionLock(*lock);
            waitForTurn->wait(conditionLock);
            conditionLock.unlock();
        }
        //function broadcast(): Let all waiting threads know they can check whether or not their car can go.
        void broadcast()
        {
            waitForTurn->notify_all();
        }
    };

    /* function monitorDirection(intersectionQueue,int,int)
    Threads will run this function.  There are four threads that run this function
    in total, one for each of the cardinal directions.  The threads check to see
    if the car at the front of the intersectionQueue, which contains the arrival order
    of cars regardless of direction, is the car at the front of the queue for the
    direction the thread is assigned to monitor.  If not, it waits on a condition
    variable until it is the case. It then calls the function to clear the intersection.
    Broadcast is then used on the condition variable so all drivers will check if they
    are allowed to pass, which one will unless there are 0 waiting cars, waiting again if not the case.
    */
    void monitorDirection(intersectionQueue *intersection, int direction, int id)
    {
        while (true) //Do forever to see if crashes can occur.
        {
            //Do nothing if there are no cars coming from this direction.
            //Possibly add more condition_variables for each direction?
            if (!intersection->empty(direction))
            {
                while (!intersection->isAtFront(direction))
                    intersection->waitInLine();
                intersection->clearIntersection(direction);
                cout << "A car has gone " << numberToDirection(direction) << endl;
                //All cars at the intersection will check the signal to see if it's time to go so broadcast is used.
                intersection->broadcast();
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

你的罪魁祸首可能是你的while (!isAtFront(...))循环。如果在检查和后续调用waitInLine()之间调度了另一个线程,则队列的状态可能会发生变化,从而导致所有的消费者线程都等待。那时候没有信号通知你condition_variable,所以他们会永远等待。