[英]Multithreading application has no output
我正在做一個處理多線程運動的應用程序,假設我們有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;
}
問題是沒有輸出,似乎所有線程都被阻塞等待。
這里有兩個問題:
首先,當您構造lock
對象時
unique_lock<mutex> lock(cars_mux);
然后cars_mux
被鎖定。 因此,嘗試在同一線程中再次鎖定cars_mux
是一個錯誤( 未定義行為 ),這是您嘗試在while
循環中立即執行的操作
cars_mux.lock();
其次,線程無法加入,因為無法退出task
的while(true)
循環-汽車將永遠停泊! 您根本不需要while
循環。
如果刪除第一個cars_mux.lock();
,在while
循環結束時進行的相應解鎖嘗試以及while
循環本身,您應該會獲得所需的行為。
弗雷澤的答案很好,但是當我看這個時,我覺得一個可行的例子會很好。
我進行了一些更改:
就個人而言,我喜歡使用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的建議的簡化代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.