简体   繁体   English

使用std :: thread的C ++多线程应用程序在Windows上可以正常工作,但在Ubuntu上却不能

[英]C++ multithreaded application using std::thread works fine on Windows but not Ubuntu

I have a somewhat simple multithreaded application written using the C++ std::thread library for both Ubuntu 14.04 and Windows 8.1. 我有一个使用C ++ std :: thread库为Ubuntu 14.04和Windows 8.1编写的稍微简单的多线程应用程序。 The code is nearly completely identical except that I'm using the operating system respective libraries windows.h and unistd.h to use Sleep/sleep to pause execution for a time. 该代码几乎完全相同,除了我使用操作系统各自的库windows.h和unistd.h来使用Sleep / sleep暂停执行一段时间。 They both actually begin to run and the Ubuntu version does keep running for a short time but then hangs. 它们实际上都已开始运行,并且Ubuntu版本确实可以保持运行一小段时间,但随后挂起。 I am using the proper arguments to the sleep/Sleep functions since I know Windows Sleep takes milliseconds, while Unix sleep takes seconds. 因为我知道Windows睡眠需要几毫秒,而Unix睡眠需要几秒钟,所以我在使用sleep / Sleep函数的适当参数。

I've run the code multiple times and on Ubuntu it never makes it past two minutes whereas I've run it on windows twice for 20 minutes and then multiple times for roughly five minutes each to see if I was just lucky. 我已经多次运行该代码,而在Ubuntu上它从未超过两分钟,而我已经两次在Windows上运行了20分钟,然后多次在Windows上运行了大约五分钟,看看我是否很幸运。 Is this just an incompatibility with the thread library or does sleep not do what I think it does, or something else? 这仅仅是与线程库不兼容,还是睡眠不按照我的想法做,还是其他? The infinite loops are there because this is a school project and is expected to run without deadlocks or crashing. 那里存在无限循环,因为这是一个学校项目,并且有望在没有死锁或崩溃的情况下运行。

The gist is that this is a modified 4-way stop where cars who arrive first don't have to slow down and stop. 要点是,这是一种经过改进的四向停车,在这种情况下,先到达的汽车不必减速停车。 We only had to let one car through the intersection at a time which takes 3 seconds to cross, hence Sleep(3000), and don't have to worry about turns. 我们只需要让一辆汽车通过十字路口,这需要3秒钟的时间通过,因此Sleep(3000),而不必担心转弯。 Three threads run the spawnCars function and there are four other threads that each monitor one of the four directions N, E, S, and W. I hope that it's understandable why I can't post the entire code in the chance some other student stumbles upon this. 三个线程运行spawnCars函数,还有四个其他线程分别监视N,E,S和W四个方向之一。我希望可以理解为什么我不能发布整个代码,以防其他学生跌倒在此。 These two functions are the only place where code is different aside from the operating system dependent library inclusion at the top. 除了顶部包含依赖于操作系统的库以外,这两个函数是唯一代码不同的地方。 Thanks. 谢谢。

edit: Since I've just gone and posted all the code for the project, if the problem does end up being a deadlock, may I request that you only say so, and not post an in depth solution? 编辑:由于我刚刚离开并发布了该项目的所有代码,因此如果问题最终陷入僵局,我是否可以要求您只说一句,而不发布深入的解决方案? I'm new here so if that's against the spirit of SO then fire away and I'll try to figure it out without reading the details. 我是新来的,因此,如果这与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();
            }
        }
    }

Your culprit is likely your while (!isAtFront(...)) loop. 罪魁祸首可能是while (!isAtFront(...))循环。 If another thread gets scheduled between the check and the subsequent call to waitInLine() , the state of your queues could change, causing all of your consumer threads to end up waiting. 如果在检查和随后的waitInLine()调用之间安排了另一个线程,则队列状态可能会更改,从而导致所有使用者线程最终都处于等待状态。 At that point there's no thread to signal your condition_variable , so they will wait forever. 那时没有线程向您发出condition_variable信号,因此它们将永远等待。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM