2011-08-06 14 views
0

我在嘗試創建多線程服務器時遇到了一些問題。一切工作正常,直到我需要從服務器中刪除客戶端。調用加入時Boost :: Thread訪問衝突

服務器運行在它自己的線程中,然後每個客戶端都有它自己的線程。

我對所有線程都使用boost :: thread。當我需要停止客戶端我叫

void StopClient() 
{ 
    assert(mThread); 

    mStopMutex.lock(); 
    mStopRequested = true; 
    mStopMutex.unlock(); 

    shutdown(mSocket,2); 

    mThread->join(); 
} 

添加斷點行

shutdown(mSocket,2); 

我可以看到mThread不存在!這是否意味着線程已經退出?你是否總是需要爲boost :: thread調用join()?

如果我允許代碼運行,則會出現訪問衝突錯誤。

更新

ServerThread

void StartServer() 
{ 
    assert(!mListenThread); 
    mListenThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&ServerThread::Listen, this))); 
    mUpdateThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&ServerThread::Update, this))); 
} 

void StopServer() 
{ 
    assert(mListenThread); 
    mStopRequested = true; 

      mMutex.lock(); 
      for(int i = 0; i < mClients.size(); i++) 
       mClients[i]->StopClient(); 
      mMutex.unlock(); 

    mListenThread->join(); 
} 

void Listen() 
{ 
    while (!mStopRequested) 
    { 
     std::cout << "Waiting for connection" << std::endl;   
     if(mClientSocket = accept(mServerSocket, (sockaddr*) &mServerAddr, &addrlen)) 
     { 
      mMutex.lock(); 
      if(mClients.size() > 0) 
      { 
       for(int i = 0; i < mClients.size(); i++) 
       { 
        if(mClients[i]->getClientSocket() != mClientSocket) 
        { 
         ClientThread newClient; 
         newClient.Initialise(mClientSocket); 
         mClients.push_back(&newClient); 
         mClients[mClients.size()-1]->StartClient(); 
         break; 
        } 
       } 
      } 
      else 
      { 
       ClientThread newClient; 
       newClient.Initialise(mClientSocket); 
       mClients.push_back(&newClient); 
       mClients[mClients.size()-1]->StartClient(); 
      } 
      mMutex.unlock(); 
     } 
    } 
}   

void Update() 
{ 
    while (!mStopRequested) 
    { 
     mMutex.lock(); 

     std::cout << "::::Server is updating!::::" << mClients.size() << std::endl; 
     for(int i = 0; i< mClients.size(); i++) 
     { 
      if(!mClients[i]->IsActive()) 
      { 
       mClients[i]->StopClient(); 
       mClients.erase(mClients.begin() + i); 
      } 
     } 

     mMutex.unlock(); 

    } 
} 

ClientThread

void StartClient() 
{ 
    assert(!mThread); 
    mThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&ClientThread::Update, this))); 
} 

void Update() 
{ 
    bool stopRequested; 
    do 
    { 
     mStopMutex.lock(); 
     stopRequested = mStopRequested; 
     mStopMutex.unlock(); 

     std::cout << "lol" << std::endl; 
     if(mTimeOut < 1000) 
     { 
      mTimeOut++; 
     } 
     else 
     { 
      mActive = false; 
     } 

     boost::this_thread::interruption_point(); 
    } 
    while(!stopRequested); 
} 
+4

您需要向我們展示更多的代碼。 「mThread」在哪裏設置,以及什麼值?它還用在哪裏? –

+1

「mThread不存在」是什麼意思?它是NULL還是它指向一個已刪除的對象? – mmmmmmmm

+0

感謝您的回覆。我已更新以顯示更多代碼! @Rüdiger它只是指向一個被刪除的對象。 – kiwijus

回答

1
  ClientThread newClient; 
      newClient.Initialise(mClientSocket); 
      mClients.push_back(&newClient); 

這在棧上的局部變量,並把它的地址到你的mClients的列表。然後範圍結束,局部變量也結束。這會讓你的名單mClients指向不再有的東西。

+0

這是一個好點! 我已將代碼更改爲 'ClientThread * newClient = new ClientThread(); newClient-> Initialise(mClientSocket); mClients.push_back(newClient);' 現在它工作! :) 謝謝! – kiwijus

0

有沒有足夠的代碼在這裏,以確定到底發生了什麼事情,但這裏有事情要檢查:

  • 您的客戶端線程中可能有一個處理循環正在檢查mStopRequested成員。在處理循環退出之前,它是否改變了mThread成員?
  • 當你得到訪問衝突時,mThread是NULL嗎?或者,它有其他價值嗎?在將mStopRequested設置爲true之前它有效嗎?