3. Thread.h——封裝thread

該類封裝了thread的create忿等、join栖忠、detach等操作。

多線程中系統(tǒng)中將要大量使用線程操作函數(shù)。
為了擴展和維護方便庵寞,將這些函數(shù)風和鉆掛在一個類中狸相,也符合oop的理念。

muduo是這樣做的:

  1. 一個類捐川,來封裝需要執(zhí)行的函數(shù)脓鹃,并捕獲線程創(chuàng)建時可能的錯誤。
    該類是一個struct属拾,有一個構造函數(shù)用于初始化類中變量将谊。
    有一個函數(shù),用于在線程中被調(diào)用渐白。
struct ThreadData 
{
  //別名
  typedef boost::function<void ()> ThreadFunc;
  //數(shù)據(jù)
  ThreadFunc _func;//被調(diào)用的函數(shù)
  string _name;  //用于排錯的線程名  
  //構造函數(shù)  
  ThreadData(const ThreadFunc &func, const string &name):_func(func),_name(name){}
  //被調(diào)用的函數(shù)
  void runInThread()
  {
    //CurrentThread中的獲取當前線程尊浓。  
    pid_t   tid=tid();
    //給線程設置名字〈垦埽可以使用ps -eL查看栋齿。用于拍錯。
    prctl(PR_SET_NAME,_name.c_str());
    try
    {
      _func();
    }
    catch ()
    {
       //如果出錯襟诸,設置threadName
    }
  }
}
  1. 定義一個通用函數(shù)瓦堵,作為pthread_create的第三個參數(shù),這個函數(shù)將調(diào)用傳入的結構體中的一個函數(shù)歌亲。
void* start(void* i)
{
  ThreadData *data=static_cast<ThreadData *>i;
  data->runInThread();
  delete data;//這里的應該是棧上的變量吧菇用。不需要
  return NULL;
}

3。然后一類陷揪,用來控制線程的執(zhí)行惋鸥。相當于一個代理類的感覺『凡可以先初始化一個線程卦绣,等到合適的時候執(zhí)行。

class Thread
{
//別名
typedef boost::function<void ()> ThreadFunc;
private飞蚓;
  ThreadFunc _func;//實際調(diào)用的函數(shù)
  string _name; //對線程起的名字
  bool _started;//記錄是否已經(jīng)創(chuàng)建過線程
  bool _joined;//記錄是否已經(jīng)等待結束滤港,回收資源。
  pthread_t _pthread;  //線程id用于回收資源
public:
  Thread(const ThreadFunc &func趴拧, const string &name):_func(func),_name(name),_started(false),_joided(false),_tid(0),_pthread(0);
  ~Thread()
  {
    if(_started&&!_joined)
    {
        pthread_detach(_pthread);
    }
  }
  void start()
  {
    assert(_started);
    _started=true;
    ThreadData *data=new ThreadData(_func,_name);
    if(pthread_create(&thread,NULL,runInThread,data))
    {
      _started=false;      
    }
    delete data;
  }
  int joid(0
  {
    assert(_joided);
    assert(_started);
    _joined=ture;
    return pthread_join(_pthread,NULL);
  }
}

基礎

int pthread_create(pthread_t , const pthread_attr_t,void (func)(void), void *)

創(chuàng)建新的線程,立即執(zhí)行傳入的函數(shù)溅漾。成功返回0,否則返回錯誤編號。

pthread.h庫中著榴,但該庫不是c的標準哭樟凄,所以在編譯的時候需要在后面顯式的加上-lpthread

這是多線程的基礎兄渺。
第一個參數(shù)是線程id缝龄,pthread_t的結構體汰现。傳入后,由函數(shù)進行填充叔壤。
第二個參數(shù)是控制參數(shù)瞎饲。可為空
第三個參數(shù)是一個函數(shù)指針(也就是函數(shù)名)炼绘。這個函數(shù)必須是void *func(void *)嗅战,它有一個參數(shù)是void *類型的。如果有多個參數(shù)沒那么需要在放在一個結構體中俺亮。
第四個參數(shù)傳入的參數(shù)指針或者結構體的指針驮捍。可為空

#include <pthread.h>

struct arg
{
  int i;
  char c;
};
//func
void *func(void *a)
 {
  //轉(zhuǎn)化后才可以使用
  struct arg *tmp=(struct arg *)a;  
}

int main()
{
  //填充結構體
  struct arg arg1;
  arg1.i=1;
  arg1.c='u'脚曾;

  pthread_t tid1;
  int result = pthread_create(&tid1, NULL, func, &arg1);
}

pthread_t pthread_self()和gettid()

判斷兩個線程是否相同

pthread_t

線程的id

是一個結構體东且,可已通過pthread_t pthread_self()來返回當前線程的id。同時使用int pthread_equal(pthread_t ,pthread_t)來判斷兩個線程id是否相同本讥,不同時返回0珊泳。

但是,這個結構體在多線程的時候有問題:不同進程中線程的線程id可能相同拷沸。所以不是作為判斷線程相同的條件色查。

gettid()

所以,常用gettid()來判斷似乎否是同一個線程.
但是撞芍,標準c沒有實現(xiàn)這個函數(shù)秧了,所以需要使用系統(tǒng)調(diào)用。

int syscall()

系統(tǒng)調(diào)用函數(shù)序无,返回int
unistd.h

pid_t pid1=(pid_t)syscall(SYS_gettid);

同上使用上述函數(shù)來獲取tid验毡。
其中SUS_gettid,在sys/syscall.h中。

返回的值作為系統(tǒng)中線程中唯一的id愉镰。

其中米罚,進程中唯一線程的pid_t和通過getpid()的返回值相同钧汹。

線程回收

等待線程執(zhí)行結束丈探,和回收資源。

線程在函數(shù)執(zhí)行結束以后拔莱,需要回收資源碗降。
線程有兩種狀態(tài)joinableunjoinable
unjoinable下塘秦,線程所使用的資源不會被釋放讼渊,直到joinable

pthread_join(pthread_t,void *)

使函數(shù)變?yōu)?code>joinable

第一個參數(shù)是線程id尊剔,第二個參數(shù)可以是函數(shù)的返回值爪幻,如果是NULL表示我們不關心函數(shù)的返回值。如果需要返回值,需要先創(chuàng)建對應的結構體挨稿,然后傳入指針仇轻,讓函數(shù)填充。

程序?qū)谠撜Z句出堵塞奶甘,直到線程執(zhí)行完畢返回篷店。即使有很多該函數(shù)也會依次執(zhí)行。
int pthread_atfork(void (prepare)(void), void (parent)(void), void (*child)(void));

pthread_detach(pthread_t)

即使函數(shù)沒執(zhí)行完也可以使用該函數(shù)制定線程的狀態(tài)

執(zhí)行該函數(shù)后臭家,線程中函數(shù)運行結束后直接釋放所消耗的資源疲陕。

prctl()

可以設置和獲取線程的名字

prctl(PR_SET_NAME,"name");
prctl(PR_GET_NAME,buf);//如果沒設置那么獲取的是值是`getid`

為fork和pthread注冊函數(shù)

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

pthread_atfork()在fork()之前調(diào)用,當調(diào)用fork時钉赁,內(nèi)部創(chuàng)建子進程前在父進程中會調(diào)用prepare蹄殃,內(nèi)部創(chuàng)建子進程成功后,父進程會調(diào)用parent 橄霉,子進程會調(diào)用child窃爷。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市姓蜂,隨后出現(xiàn)的幾起案子按厘,更是在濱河造成了極大的恐慌,老刑警劉巖钱慢,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逮京,死亡現(xiàn)場離奇詭異,居然都是意外死亡束莫,警方通過查閱死者的電腦和手機懒棉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來览绿,“玉大人策严,你說我怎么就攤上這事《銮茫” “怎么了妻导?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長怀各。 經(jīng)常有香客問我倔韭,道長,這世上最難降的妖魔是什么瓢对? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任寿酌,我火速辦了婚禮,結果婚禮上硕蛹,老公的妹妹穿的比我還像新娘醇疼。我一直安慰自己硕并,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布秧荆。 她就那樣靜靜地躺著鲤孵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辰如。 梳的紋絲不亂的頭發(fā)上普监,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音琉兜,去河邊找鬼凯正。 笑死,一個胖子當著我的面吹牛豌蟋,可吹牛的內(nèi)容都是我干的廊散。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼梧疲,長吁一口氣:“原來是場噩夢啊……” “哼允睹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起幌氮,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缭受,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后该互,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體米者,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡吻商,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年刑棵,在試婚紗的時候發(fā)現(xiàn)自己被綠了肮塞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趋艘。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖跷究,靈堂內(nèi)的尸體忽然破棺而出肴掷,到底是詐尸還是另有隱情块蚌,我是刑警寧澤机蔗,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布蒲祈,位于F島的核電站,受9級特大地震影響蜒车,放射性物質(zhì)發(fā)生泄漏讳嘱。R本人自食惡果不足惜幔嗦,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一酿愧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邀泉,春花似錦嬉挡、人聲如沸钝鸽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拔恰。三九已至,卻和暖如春基括,著一層夾襖步出監(jiān)牢的瞬間颜懊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工风皿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留河爹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓桐款,卻偏偏與公主長得像咸这,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子魔眨,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容