線程的退出與其相關資源的釋放


線程是可訪問進程資源的獨立運行的一系列代碼(過程),它使用的資源有兩種:
1.進程中所有線程共享的資源。
2.線程私有的資源。
那麼如果線程退出的話,第2種資源也就沒有存在的意義了。

線程退出的方式:
1.線程的入口函數執行完畢,這是最自然的退出方式,也是最佳的退出方式。
2.使用ExitThread系統API函數,在類UNIX系統的相應函數是pthread_exit。
3.使用TerminateThread系統API函數,類UNIX相應函數是pthread_cancel。它最好與WaitSingleObject或

pthread_mutex一起使用,這種退出方式你無法計算線程的具體退出位置。

線程退出的原因:
1.最自然的方式,線程工作完畢,退出。
2.線程在工作出現了問題,要將自身退出。
3.外部線程管理此線程,在不再需要此線程執行的情況下,將其退出。

線程退出的方法:
1.使用全局變量或是線程封裝類成員變量表示線程工作狀態。
2.設置全局的事件或線程封裝類事件成員變量表示線程工作狀態,在pthread類庫中有專門的事件處理函數。
3.向線程發送事件的方式(只有Windows提供)
4.使用強制退出的方法,也就是TerminateThread。

線程資源的釋放方法:
1.外部線程WaitForSingleObject,發現線程中止運行後,釋放線程相關的資源。
如:
void main()
{
 CThread thread; //一個自己定義的線程封裝類,其中有一些成員變量,Start啓動線程函數,Release釋

放資源函數。
 thread.Start();
 while(WaitForSingleObject(thread.m_hThread,1000) != WAIT_OBJECT_0)
 {
  //TerminateThread(thread.m_hThread);//在這裏如果你不想再等待,可以中止它
  Sleep(1000);
 }
 thread.Release();
}

這種方式的優點是對線程的全面的管理。
缺陷在於,如果要即時釋放資源,必須有一個專門的外部的線程來不斷的監視或管理線程運行狀態。

2.線程退出時將自身資源釋放:
如:
DWORD CALLBACK CThread::Thread(VOID *pParam) //線程的入口函數,static函數
{
 CThread *pthread = pParam;
 ... //工作狀態設置
 pthread->Execute()
 ... //工作狀態設置
 pthread->Release() //在所有的工作做完之後進行釋放資源
 return 0;
}

這種方式的優點是對線程的資源的時機是最準確的,缺陷是必須要保證線程在需要退出時不會阻塞。

在實際的工作中,我們需要這多種方式的集合來實現我們的功能:
如有個網絡服務器,它給每個用戶的新建一個線程來響應它的請求,如果用戶退出,要保證相關資源要完整的釋

放,並且服務器本身有停止功能,停止時,不論有多少和用戶交互,都必須中止所有線程,且釋放所有資源。
要解決的子問題:
1.用戶退出時資源釋放:
解決方式:
1.使用線程自身退出時釋放的方式。
2.使用一個外部監視線程,發現線程退出時釋放相應的資源。

2.服務器停止時退出且釋放所有線程:
設用戶線程工作狀態爲停止,
等待用戶線程自然退出,如果沒有退出,可能是阻塞狀態。這時使用強制退出的方法。
釋放所有用戶線程相關的資源,可以根據資源的使用時間和方式(如某些Windows資源句柄),
在線程退出之前的某時機進行釋放。

下面是我實作的滿足以上要求的自身退出方式釋放資源的線程類的代碼片段:

int CThread::Stop()
{
 m_RunningMutex.Lock(); //判斷線程的工作狀態,如果已經退出,直接返回
 if(!m_bRunning)
 {
  m_RunningMutex.Unlock();
  return ERR_VTHREAD_ALREAD_STOP;
 }
 m_RunningMutex.Unlock();

 m_StopMutex.Lock();
 m_bStop = True;  //設置線程的工作狀態爲停止
 m_StopMutex.Unlock();

#ifdef _WIN32
 DWORD ThreadId = GetCurrentThreadId(); //判斷是否線程自身退出,如果是,則返回,不能調用強

制退出的方法
#else
 pthread_t ThreadId = pthread_self();
#endif

 if(ThreadId != m_ThreadID)
 {
  m_dwExitMode = EXIT_BY_OTHER;
 }
 else
 {
  m_dwExitMode = EXIT_BY_SELF;
 }

 if(m_dwExitMode == EXIT_BY_OTHER) //如果是服務器停止信號
 {
  int nTryTime = 0;
  bool bStopTry = false;
  while( m_bRunning && !bStopTry) //嘗試判斷線程是否停止,最好使線程自然退出
  {
   if (nTryTime > m_nStopWaitTime)
    bStopTry = true;
   Sleep(10000);
   nTryTime ++;
  }

  if(bStopTry) //如果線程沒有退出,就強制退出
#ifdef _WIN32
   TerminateThread(m_hThread, DEF_EXIT_CODE);
#else
   pthread_cancel(m_ThreadID);
#endif
  m_RunningMutex.Lock();
  m_bRunning = False;
  m_RunningMutex.Unlock();

  Release(); //線程已經停止,釋放所有私有次源,這行代碼可以在服務器端,讓此函數只執

行停止功能
 }
 return 0;
}

 

//這是線程的主函數,它包含的釋放自身私有資源的功能。
#ifdef WIN32
DWORD __stdcall CThread::ThreadProc( VOID *lpParameter )
#else
VOID* CThread::ThreadProc( VOID *lpParameter )
#endif
{
 BOOL bStop;
#ifndef _WIN32
 //pthread_detach(pthread_self());
#endif

 CThread* pThread = (CThread*)lpParameter;

 pThread->m_RunningMutex.Lock();
 pThread->m_bRunning = True;
 pThread->m_RunningMutex.Unlock();

 pThread->m_StopMutex.Lock();
 bStop = pThread->m_bStop;
 pThread->m_StopMutex.Unlock();

 if( !bStop)
 {
  pThread->Execute();
 }

 pThread->m_RunningMutex.Lock();
 pThread->m_bRunning = False;
 pThread->m_RunningMutex.Unlock();

 if(pThread->m_dwExitMode == EXIT_BY_SELF) //在這裏判斷線程是否自身退出,如是:釋放私有資源


 {
  pThread->Release();
 }

 //退出線程,使線程以最自然的方式退出.

 return 0;
}

希望和大家討論:[email protected]

發佈了36 篇原創文章 · 獲贊 2 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章