2011-03-22 103 views
1

我有以下程序:问题在程序执行的线程

#include "stdafx.h" 
#include <boost/thread/thread_time.hpp> 
#include <boost/thread/thread.hpp> 
#include <iostream> 
using namespace std; 

class DogDoor { 
    bool open; 
public: 
    DogDoor() 
    { 
     this->open = false; 
    } 
    void Open() 
    { 
     cout << "The dog door opens" << endl << endl; 
     open = true; 
    } 
    void close() 
    { 
     cout << "The dog door closes" << endl << endl; 
     open = false; 
    } 
    bool isOpen() 
    { 
     return open; 
    } 
}; 

class Remote { 
    DogDoor* door; 
public: 
    Remote(DogDoor* door) 
    { 
     this->door = door; 
    } 
    void pressButton() 
    { 
     cout << "Pressing the remote button" << endl; 
     if(door->isOpen()) 
     { 
      door->close(); 
     } 
     else 
     { 
      door->Open(); 
      // close after 5 seconds 
      boost::posix_time::seconds workTime(5); 
      boost::this_thread::sleep(workTime); 
      door->close(); 
     } 
    } 
}; 

void threadFunc(Remote* r) 
{ 
    r->pressButton(); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    DogDoor* door = new DogDoor(); 
    Remote* remote = new Remote(door); 

    cout << "Fido barks to go outside" << endl; 
    boost::thread workerThread(threadFunc, remote); 

    cout << "Fido has gone outside" << endl; 

    cout << "Fido is all done..." << endl; 

    cout << "Fido is back inside" << endl; 

    workerThread.join(); 

    delete door; 
    delete remote; 

    return 0; 
} 

我希望程序打印:

Fido barks to go outside 
Pressing the remote button 
The dog door opens 
Fido has gone outside 
Fido is all done... 
Fido is back inside 
// and then after 5 seconds it should print this 
The dog door closes 

但我实现它会打印这样的,我不知道如何使它打印良好:

Fido barks to go outside 
Fido has gone outside 
Fido is all done... 
Fido is back inside 
Pressing the remote button 
The dog door opens 
// this after 5 seconds 
The dog door closes 

回答

3

你需要让主线程等待,直到门被打开:

class DogDoor 
{ 
    bool open; 
public: 
    // If you want to go through this door you should call 
    // this method. If the door is not open you are suspended. 
    // until somebody opens the door. 
    void goThroughDoor() 
    { 
     boost::unique_lock<boost::mutex> lock(mut); 
     while(!open) 
     { 
      // Note this is a while loop here. 
      // Just because all the waiting threads are un-sespended when the 
      // door is opened, it does not mean that they will get scheduled 
      // to run before the door closes. So after the thread wakes up and 
      // starts to run we need to re-check if the door is still open. 
      // 
      // If it took to long to wake up, then we have to wait again for 
      // the door to be opened. 
      // 
      // Thus this would be a good place to bark. 
      // Which may cause the remote button to be pushed. 
      // 
      waiter.wait(mut); 
     } 
    } 


    DogDoor() 
    { 
     this->open = false; 
    } 
    void Open() 
    { 
     boost::unique_lock<boost::mutex> lock(mut); 
     cout << "The dog door opens" << endl << endl; 
     open = true; 

     waiter.notify_all(); 
    } 
    void close() 
    { 
     boost::unique_lock<boost::mutex> lock(mut); 
     cout << "The dog door closes" << endl << endl; 
     open = false; 
    } 
    bool isOpen() 
    { 
     boost::unique_lock<boost::mutex> lock(mut); 
     return open; 
    } 


    private: 
     boost::condition_variable waiter; 
     boost::mutex    mut; 

}; 

现在,您需要修改主要以确保狗调用goThroughDoor()。

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    DogDoor* door = new DogDoor(); 
    Remote* remote = new Remote(door); 

    cout << "Fido barks to go outside" << endl; 
    boost::thread workerThread(threadFunc, remote); 

    // This will suspend this thread if the door is locked. 
    // When the door is opened the thread will resume.  
    door->goThroughDoor(); 


    cout << "Fido has gone outside" << endl; 

    // Should check the door is open 
    // When Fido tries to come in. If it is closed he will be suspended. 
    // And thus will not get back in. (Note he should have a way of barking 
    // if he is blocked but that I leave to you).  
    door->goThroughDoor(); 
    cout << "Fido is all done..." << endl; 

    cout << "Fido is back inside" << endl; 

    workerThread.join(); 

    delete door; 
    delete remote; 

    return 0; 
} 
+0

非常感谢你 – Kobe 2011-03-22 22:25:38

4

没有说你的开始线程必须马上执行;在join()调用显式丢弃CPU之前,它可能不会被调度运行。虽然你可以尝试调用Boost的道德等效yield(),在完整的程序中没有任何东西可以保证线程想要实际运行会运行

为确保您等待子线程执行,您需要使用一些thread synchronization工具(例如互斥锁或条件变量),以便您的子线程可以通知主线程它已完成任务。如果您将电话移至join()更靠近产卵程序的位置,则可以确定线程已完成,但这可能仅适用于玩具应用程序。在非平凡的应用程序中,您需要使用mutexcondition variable来表示线程之间特定的“已完成作业”条件。

+0

谢谢,我会尝试使用syncronization – Kobe 2011-03-22 22:14:55

3

首先,值得注意的是,从大多数观点来看,这几乎是线程/线程的最坏可能使用。特别是,两个线程都不能自己做任何事情 - 一个线程中的所有内容都需要与另一个线程中的某些内容进行同步。

这几乎是你遇到的问题 - 你没有同步到你需要的任何地方。你的序列需要是这个样子:

Fido barks 
ask door to open 
wait for confirmation that door has opened 
Fido leaves 
Fido returns 
ask door to close 
wait for confirmation that door has closed 
join 
exit 

从本质上讲,一个线程中的每一个动作依赖于其他线程的东西,所以即使你有两个线程,没有它可以并行执行。