多线程应用程序没有输出

时间:2012-07-05 21:05:53

标签: c++ multithreading c++11

我正在做一个处理多线程练习的应用程序。我们假设我们有10辆车,并且有一个停车场,最多可以包含5辆车。如果一辆车无法停车,它会等到有空房间。
我用c ++ 11线程做这个:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

int cars=0;
int max_cars=5;
mutex cars_mux;
condition_variable cars_cond;

bool pred()
{
    return cars< max_cars;
}

void task()
{
    unique_lock<mutex> lock(cars_mux);
    while(true)
    {
        cars_mux.lock();
        cars_cond.wait(lock,pred);
        cars++;
        cout << this_thread::get_id() << " has parked" << endl;
        cars_mux.unlock();
        this_thread::sleep_for(chrono::seconds(1));  // the cars is parked and waits some time before going away
        cars_mux.lock();
        cars--;
        cars_cond.notify_one();
        cars_mux.unlock();
    }
}

int main(int argc, char** argv)
{
    thread t[10];
    for(int i=0; i<10; i++)
        t[i]=thread(task);
    for(int i=0; i<10; i++)
        t[i].join();
    return 0;
}

问题在于没有输出,似乎所有线程都被阻塞等待。

2 个答案:

答案 0 :(得分:3)

这里有两个问题:

首先,构建lock对象

unique_lock<mutex> lock(cars_mux);

然后cars_mux被锁定。因此,尝试在同一个线程中再次锁定cars_mux是一个错误(undefined behaviour),这是您尝试在while循环中立即执行的操作

cars_mux.lock();

其次,线程无法加入,因为无法退出while(true)中的task循环 - 汽车将继续永久停放!您根本不需要while循环。

如果删除第一个cars_mux.lock();while循环结束时的相应解锁尝试以及while循环本身,则应该获得所需的行为。

答案 1 :(得分:2)

弗雷泽的答案很棒,但当我看到这个时,我觉得一个有效的例子会很好。

我做了一些改变:

  • 就个人而言,我喜欢使用RAII来锁定/解锁,这样你就不会忘记这样做(即使它意味着额外的范围)。在过去,我也遇到了一些我无法弄清楚的竞争条件,而转换到RAII方法往往也会让它们消失......它更容易,所以这样做;)

  • 我喜欢看车何时离开,所以我也为此添加了I / O.

这是所述问题的工作代码示例。仅供参考,我使用clang 3.1和libc ++:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

using namespace std;

int cars=0;
int max_cars=5;
mutex cars_mux;
condition_variable cars_cond;

bool pred()
{
    return cars < max_cars;
}

void task()
{
    {
        unique_lock<mutex> carlock(cars_mux);
        cars_cond.wait(carlock,pred);
        cars++;
            cout << "Thread " << this_thread::get_id() 
                 << " has parked. There are " << cars << " parked cars." << endl;
    }

    this_thread::sleep_for(chrono::seconds(1));

    {
        unique_lock<mutex> carlock(cars_mux);
        cars--;
        cout << "Thread " << this_thread::get_id() 
             << " has left. There are " << cars << " parked cars." << endl;
        cars_cond.notify_one();
    }
}

int main(int argc, char** argv)
{
    const int NumThreads = 10;
    thread t[NumThreads];
    for(int i=0; i<NumThreads; i++)
        t[i]=thread(task);
    for(int i=0; i<NumThreads; i++)
        t[i].join();
    return 0;
}

编辑:根据Rami Al Zuhouri的建议简化代码。