1. 程式人生 > >跟我一起用C++實現Java Thread庫(一)

跟我一起用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執行緒間通訊互斥機制

  • 支援執行緒組等特性。

  • ....

想要獲取更多幹貨?歡迎訂閱微信公眾號----軟體程式設計之路