JTHREAD剖析__多線程

來源:互聯網
上載者:User
1.JTHREAD介紹

實際項目中經常會涉及到多線程架構。為了給WINUX(Windows+Linux)平台提供一套相同的操作線程的介面,需要將平台上對線程操作的API封裝成一個的通用類。JTHREAD即是這樣的一個開源類庫。

JTHREAD是很簡單的,主要包含JThread類和JMutex類,它們分別代表一個線程和一個互斥體,互斥體是為了同步多線程通訊。該開發包作了簡單的跨平台實現,對於*NIX平台叫用pthread庫,對於Windows平台叫用Win32 Theads庫。

本文基於JTHREAD庫源碼做簡單剖析,以對前麵線程式控制制、線程同步等議題實做演練。

按照慣例,對於返回int類型值的函數,若返回大於等於0的值表示成功,負值表示出錯。

  2.JMutex 2.1 JMutex

下面是類JMutex的定義。

[cpp]  view plain copy print ? class JMutex   {   public:       JMutex();       ~JMutex();          int Init();       int Lock();       int Unlock();       bool IsInitialized() { return initialized; }      private:      #if (defined(WIN32) || defined(_WIN32_WCE))   #ifdef JMUTEX_CRITICALSECTION       CRITICAL_SECTION mutex; // 臨界區對象   #else // Use standard mutex       HANDLE mutex;           // 互斥核心對象   #endif // JMUTEX_CRITICALSECTION   #else // pthread mutex       pthread_mutex_t mutex;   #endif // WIN32          bool initialized;   };  

        其資料成員根據平台區分。對於Windows系統(Win32或WinCE),若定義JMUTEX_CRITICALSECTION宏,則使用臨界區對象CRITICAL_SECTION作為互斥體;否則,使用互斥核心對象(Mutex)作為互斥體。對於*NIX系統使用pthread_mutex_t作為互斥體。後面主要針對Windows系統解說,鑒於臨界區旋轉鎖的高效性,建議使用JMUTEX_CRITICALSECTION。

int Init()完成互斥體的初始化;bool initialized跟蹤初始化記錄,確保只初始化一次。可調用bool IsInitialized()擷取initialized的值,以判斷是否已經初始化。

在int Init()中,如果定義了JMUTEX_CRITICALSECTION宏,則調用InitializeCriticalSection(&mutex)初始化臨界區;否則mutex = CreateMutex(NULL,FALSE,NULL),建立互斥核心對象。

Lock()/Unlock()為同步加解鎖操作。Lock()內部體現為EnterCriticalSection(&mutex)進入臨界區,或WaitForSingleObject(mutex,INFINITE)返回,可擁有互斥對象。Unlock()內部體現為LeaveCriticalSection(&mutex)離開臨界區,或ReleaseMutex(mutex)釋放擁有的互斥對象。

建構函式JMutex()中初始化initialized = false;解構函式~JMutex()中DeleteCriticalSection(&mutex)刪除臨界區或CloseHandle(mutex)關閉互斥核心對象,釋放互斥體資源。

在你使用一個JMutex類的執行個體對象之前,你首先必須調用Init()函數執行初始化。通過檢測IsInitialized()的傳回值可以檢測互斥體是否已經初始化。初始化之後,通過調用Lock()和Unlock()封閉需要同步的共用資源作業碼段。 2.2 JMutexAutoLock

下面是類JMutexAutoLock的定義。

[cpp]  view plain copy print ? class JMutexAutoLock   {   public:       JMutexAutoLock(JMutex &m) : mutex(m) { mutex.Lock(); }       ~JMutexAutoLock() { mutex.Unlock(); }      private:       JMutex &mutex;   };  

JMutexAutoLock需要傳入一個JMutex對象的引用來構造,當然,要求該JMutex對象已經初始化。在建構函式中調用mutex.Lock()上鎖,在解構函式中mutex.Unlock()解鎖。

JMutexAutoLock即所謂的自動鎖,是對JMutex的自動管理,同步對象聲明到對象生命週期結束之間的程式碼片段(塊)。它更容易實現安全執行緒,不用去擔心什麼時候為互斥體解鎖。 2.3 JMutex樣本

[cpp]  view plain copy print ? JMutex mutex;   mutex.Init();      void DoSomeWork();      void fun1()   {       mutex.Lock();       mutex.Unlock();       DoSomeWork();          return;   }      void fun2()   {       mutex.Lock();       DoSomeWork();       mutex.Unlock();              return;   }      void fun3()   {       JMutexAutoLock AutoLock(mutex);       DoSomeWork();          return;   }  

(1)在fun1()中,mutex.Lock();和mutex.Unlock();之間沒有任何代碼,則此處只是等待外部使用mutex保護的代碼塊運行完畢。如果外部佔用該mutex,則此處等待;如果外部已釋放該mutex,則此處繼續執行DoSomeWork()。這裡純粹是等待外來事件發生:後上鎖的等待先上鎖的解鎖

(2)fun2()和fun3()是等價的,都是為了保護DoSomeWork()過程中涉及到的共用資源操作。

(3)在fun3()中,如果DoSomeWork()中途異常exit,則AutoLock不能正確析構,永遠不會解鎖。在此等待的後續線程(如果沒有當掉)死結。

  3.JThread

下面是JThread類的定義。

[cpp]  view plain copy print ? class JThread   {   public:       JThread();       virtual ~JThread();          int Start();       int Kill();       virtual void *Thread() = 0;       bool IsRunning();       void *GetReturnValue();      protected:       void ThreadStarted();      private:      #if (defined(WIN32) || defined(_WIN32_WCE))   #ifdef _WIN32_WCE       DWORD threadid;       static DWORD WINAPI TheThread(void *param);   #else   UINT threadid;   static UINT __stdcall TheThread(void *param);      #endif // _WIN32_WCE       HANDLE threadhandle; //    #else // pthread type threads       pthread_t threadid;       static void *TheThread(void *param);   #endif // WIN32          void *retval;       bool running;              JMutex runningmutex;       JMutex continuemutex,           continuemutex2;          bool mutexinit;   };   3.1JThread成員

threadid為線程ID號,threadhandle為線程核心物件控點。

JThread類擁有三個JMutex對象成員,runningmutex、continuemutex和continuemutex2。bool mutexinit為三個對象初始化狀態記錄,只有三個互斥對象都成功初始化,才能協作完成後續對線程流程的正確控制。

TheThread(void *param)為通常意義上的線程入口函數,傳遞一個void*指標作為線程參數,該類靜態入口傳遞JThread線程對象this指標。TheThread中調用Thread()完成特定的任務。我們姑且稱TheThread()為線程殼(Shell),Thread()為線程核(Core)。

bool running為線程運行狀態;bool IsRunning()為對該狀態屬性的訪問。

void* retval為線程函數運行結果;void *GetReturnValue()為對該屬性的訪問。 3.2JThread類剖析

所謂同步是指多線程之間的同步,同一線程內部順序執行不存在同步問題。JThread類中runningmutex、continuemutex、continuemutex2主要為了與它的建立線程同步。它的建立線程就是MyJThread對象執行個體聲明代碼所在的線程,也即調用JThread::Start()的線程。注意線程殼TheThread()是為線程入口函數,其中調用MyJThread對象執行個體(this)的Thread(),線程殼TheThread()和線程核Thread()代碼運行於線程。因此,在Start()和TheThread()/Thread()間存在過程狀態控制的同步問題。

更一般的同步問題體現在MyJThread對象執行個體聲明代碼所在的線程與建立線程關於running狀態及傳回值retval的訪問。runningmutex互斥體主要用來保護running狀態變數的訪問,當然retval的訪問與running狀態密切相關,只有運行完才有傳回值。

下面結合具體代碼來分析Start()->TheThread()->Thread()的過程式控制制。

[cpp]  view plain copy print ? int JThread::Start()   {       if (!mutexinit)       {           // 初始化3個JMutex(代碼略)       }              runningmutex.Lock();       if (running)       {           runningmutex.Unlock();           return ERR_JTHREAD_ALREADYRUNNING;       }       runningmutex.Unlock();              continuemutex.Lock();          #ifndef _WIN32_WCE       threadhandle = (HANDLE)_beginthreadex(NULL,0,TheThread,this,0,&threadid);   #else       threadhandle = CreateThread(NULL,0,TheThread,this,0,&threadid);   #endif // _WIN32_WCE              if (threadhandle == NULL)       {           continuemutex.Unlock();           return ERR_JTHREAD_CANTSTARTTHREAD;       }              /* Wait until 'running' is set */       runningmutex.Lock();       while (!running)       {           runningmutex.Unlock();           Sleep(1);           runningmutex.Lock();       }       runningmutex.Unlock();              continuemutex.Unlock();         

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.