日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux创建多个子线程并回收

發(fā)布時間:2023/11/30 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux创建多个子线程并回收 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

創(chuàng)建子線程的邏輯相比子進(jìn)程要更容易理解一些,因?yàn)榫€程沒有像進(jìn)程那樣復(fù)制很多東西另起爐灶,子線程從傳入的開始函數(shù)開始運(yùn)行,但是難點(diǎn)在于傳入?yún)?shù)和回收時獲取退出狀態(tài),因?yàn)檫@兩個原本都是void *類型的,而我們在使用時就必須進(jìn)行轉(zhuǎn)換。先上代碼,然后再根據(jù)代碼進(jìn)行解釋:

void pthread_check(int ret, const std::string msg = "error", int default_ret = 0);using std::cout; using std::endl; namespace {pthread_mutex_t mutex1; }void *func(void * argc) { // int idx = *reinterpret_cast<int *>(argc);int idx = reinterpret_cast<long>(argc);pthread_mutex_lock(&mutex1);cout << "I am thread " << idx << "\n";pthread_mutex_unlock(&mutex1);//pthread_exit(argc);return argc; }void create_multi_thread() {pthread_mutex_init(&mutex1, nullptr);constexpr int N = 5;pthread_t tid[N];void *ret;for (int i = 0; i < N; ++i) {pthread_check(pthread_create(&tid[i], nullptr, func, reinterpret_cast<void *>(i)));}pthread_mutex_lock(&mutex1);cout << "I am thread 5" << "\n";pthread_mutex_unlock(&mutex1);for (int i = 0; i < N; ++i) {pthread_join(tid[i], &ret);pthread_mutex_lock(&mutex1);cout << "thread " << i << " exits with status : " << reinterpret_cast<long>(ret) << "\n";pthread_mutex_unlock(&mutex1);}pthread_exit(0); }

其中pthread_check函數(shù)是我寫的一個用于檢查返回值的工具函數(shù),mutex1是互斥量用于加鎖控制輸出(否則可能會很亂),子線程的工作很簡單,就是輸出自己是第幾個線程。

  • 其中比較關(guān)鍵的地方就是pthread_create的第四個參數(shù):向開始函數(shù)傳參。這里我們可以看到把循環(huán)變量i轉(zhuǎn)換使用reinterpret_cast轉(zhuǎn)換成了void *類型的,然后再在開始函數(shù)func中使用reinterpret_cast函數(shù)將void *類型轉(zhuǎn)換成了long類型。

    你可能覺得奇怪,為什么要把一個int類型直接轉(zhuǎn)換成void *類型,為什么不將其地址傳入呢?首先,要想清楚為什么使用void *類型作為傳入?yún)?shù)的類型:我認(rèn)為指針類型比基本類型更加廣泛,指針類型可以保存基本類型的值,也可以指向內(nèi)存,但是基本類型是無法指向內(nèi)存的值的,因此使用空指針類型靈活度更高,這里僅僅是這個場景下需要傳入一個整數(shù)而我們不想大費(fèi)周章在堆上分配內(nèi)存罷了,如果分配內(nèi)存的話顯然是需要指針的。

    可不可以傳入int值的地址而不是將其本身傳入進(jìn)去呢?如果是單個線程應(yīng)該是沒有什么問題,但是多個子線程下就有問題了:因?yàn)樵摵瘮?shù)的棧空間是線程共享的,因此當(dāng)主控線程修改了循環(huán)變量的值以后子線程中的值也會被修改,這顯然不是我們想要的,如果還是感覺到無法理解的話可以自己手動嘗試一下。

  • 第二個問題就是為什么要在func函數(shù)中使用reinterpret_cast將void *轉(zhuǎn)換為long類型而不是int類型,因?yàn)樵贑++里面轉(zhuǎn)換成int類型會報錯說精度丟失(雖然C語言里面好像不會,我看大家都在隨便轉(zhuǎn),感覺這個轉(zhuǎn)換太魔性了,還是C++規(guī)范一些),但是一般情況下long類型和指針類型的大小是差不多大的,轉(zhuǎn)換成 long類型就不用擔(dān)心精度丟失了。

  • 第三個問題就是在使用pthread_join函數(shù)回收子線程的時候我們使用ret來獲取子線程退出狀態(tài),經(jīng)過測試發(fā)現(xiàn)在子線程的開始函數(shù)的返回值就是最后的子線程退出狀態(tài)(當(dāng)然我們也可以使用pthread_exit函數(shù))

  • ret本身是void *類型,pthread_join函數(shù)需要一個void **類型,用來接收返回的void *類型,在接收成功后我們再次將其轉(zhuǎn)換成long類型。

運(yùn)行結(jié)果如下:

總結(jié)

以上是生活随笔為你收集整理的Linux创建多个子线程并回收的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。