跟我一起用C++實現Java Thread庫(一)
本文適合對多執行緒Thread原理比較感興趣的同學閱讀,需要具備一定的C++和Java程式設計知識。
一、背景
最近學習Java多執行緒程式設計,發現Java標準庫中的java.lang.Thread介面定義十分友好簡潔,使用起來十分方便。不禁想起之前用C/C++寫多執行緒時的煩惱,總會寫一些pthread_*函式。於是萌生了這個念頭,希望用C++實現一套類似Java Thread的庫,簡化以後的C++多執行緒開發。
二、C++ Thread用法
為了最大化地接近java.lang.Thread,同時方便Java開發者快速學習C++ Thread庫,本庫在使用上與Java完全一致,示例程式碼為:
#include <iostream> #include <unistd.h> #include <Thread.h> class SimpleThread: public Thread { public: virtual void run() { Thread::run(); std::cout << "I am a Thread\n"; sleep(2); } ~SimpleThread() { std::cout << "I can free myself\n"; } }; int main(int argc, char* argv[]) { SimpleThread *thread = new SimpleThread; thread->start(); return 0; }
正如你所見,Thread類使用起來十分簡潔。你只需要包含Thread.h檔案,然後按照Java Thread的用法編寫多執行緒程式就可以了。
. |-- src | |-- Alias.h | |-- Exception | | |-- BaseException.h | | |-- IllegalArgumentException.h | | |-- IllegalThreadStateException.h | | `-- ThreadCreateFailedException.h | |-- Makefile | |-- RefCountable.h | |-- Runnable.cpp | |-- Runnable.h | |-- RunnablePtr.h | |-- Thread.cpp | |-- Thread.h | |-- ThreadEntry.cpp | |-- ThreadEntry.h | |-- UnCopyable.h | |-- _Runnable.h | `-- _Thread.h `-- test |-- Makefile |-- RunnableTest.cpp |-- SimpleThreadTest.cpp `-- SyncTest.cpp
使用之前,先進入src資料夾編譯生成靜態Thread庫:
git clone https://github.com/xhjcehust/Thread.git
cd Thread/src
make
然後編譯連結自己的main檔案,以上述SimpleThreadTest.cpp檔案為例,對應的編譯命令為:
g++ -I ../src -o SimpleThreadTest SimpleThreadTest.cpp ../src/Thread.a -lpthread
生成SimpleTest可執行檔案,執行效果為:
三、C++ Thread實現
在上面的示例中,我們發現兩件有意思的事情:
-
動態申請的SimpleThread例項不需要釋放,記憶體洩漏?No~
-
沒有pthread_join,主執行緒為何會等到子執行緒sleep 2s退出才退出?
先看下Thread庫的框架構成:
是的,你沒看錯,Thread.a呼叫了你所寫的main函式!!!在最後編譯生成的檔案之中,Main函式事實上被重新命名為__Main函式,真正地main函式隱藏在Thread.a之中。這種設計在開發者無感知的情況下將其編寫的main函式作為Thread.a的一個模組來執行,其優點在於:
-
接管main函式所代表的主執行緒,在main函式執行之後實現資源的清理工作,如join等待子執行緒執行完成
-
捕獲主執行緒執行過程中的異常,確保程序不會因為主執行緒的異常導致其他執行緒停止
但是,也給開發者帶來了一點限制:main函式的宣告的格式為:
int main(int argc, char* argv[])
但事實上,這種宣告是普遍適用的宣告方式,有利於規範平時的程式設計習慣。 另外,__Main這個符號已經被Thread庫所使用,在編寫的main檔案中也不能使用這個符號,需要重定義。
細心的讀者可能發現,示例之中的Thread物件通過new申請堆上記憶體,而不是棧上分配。主要原因在於C++棧上物件的生命週期在退棧時銷燬,而執行緒內需要引用Thread物件,因此,Thread庫限制只能在堆上構造物件,棧上構造會編譯出錯。
至於SimpleThread例項不需要主動釋放這點,在子執行緒執行完之後,Thread庫會自動釋放執行緒申請的Thread物件資源。
四、C++ Thread開發進度
到目前為止,Thread庫實現的功能包括:
-
基礎Thread類和Runnable類功能
-
synchronize同步語句塊功能
後續需要開發的功能包括:
-
執行緒停止,暫停,訊號等
-
Thread執行緒間通訊互斥機制
-
支援執行緒組等特性。
-
....
想要獲取更多幹貨?歡迎訂閱微信公眾號----軟體程式設計之路