中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

做網(wǎng)站設(shè)像素國內(nèi)廣告投放平臺

做網(wǎng)站設(shè)像素,國內(nèi)廣告投放平臺,中國寧波網(wǎng)手機首頁,做公眾號和網(wǎng)站一樣嗎多線程操作 進程與線程線程的創(chuàng)建 create_pthread創(chuàng)建線程池給線程傳入對象的指針 線程等待 pthread_join退出線程 pthread_exit線程等待參數(shù) retval 與 線程退出參數(shù) retval 線程中斷 pthread_cancel獲取線程編號 pthread_self線程分離 pthread_detach 進程與線程 進程是資源…

多線程操作

  • 進程與線程
  • 線程的創(chuàng)建 create_pthread
    • 創(chuàng)建線程池
    • 給線程傳入對象的指針
  • 線程等待 pthread_join
  • 退出線程 pthread_exit
    • 線程等待參數(shù) retval 與 線程退出參數(shù) retval
  • 線程中斷 pthread_cancel
  • 獲取線程編號 pthread_self
  • 線程分離 pthread_detach

進程與線程

  • 進程是資源分配的基本單位
  • 線程是調(diào)度的基本單位,共享進程的數(shù)據(jù),擁有自己的一部分數(shù)據(jù)

線程私有的屬性:線程的ID、一組寄存器(上下文數(shù)據(jù))、棧(獨立的棧結(jié)構(gòu))、調(diào)度優(yōu)先級

進程的多個線程共享同一塊地址空間,對堆區(qū)、棧區(qū)都是共享的

線程共享進程的資源有:文件描述符表、每種信號的處理方式(默認動作、忽略動作、自定義動作)、當(dāng)前工作目錄

線程的創(chuàng)建 create_pthread

Linux下沒有真正意義的線程,而是用進程模擬的線程(LWP)。對此,Linux不會提供直接創(chuàng)建線程的系統(tǒng)調(diào)用,只會提供創(chuàng)建輕量級進程的接口。

在用戶看來會很變扭,進程是進程,線程是線程就要區(qū)分開來。

所以出現(xiàn)了用戶級線程庫 pthread對Linux接口進行封裝,給用戶提供進行線程控制的接口

pthread 線程庫在任何版本的Linux操作系統(tǒng)都會存在, pthread也被稱為原生線程庫)

可以通過 man 的3號手冊來查看線程庫的使用,這里不作演示

接下來介紹一些線程庫的接口使用:

使用原生線程庫需要包含頭文件:#include <pthread>

  • 創(chuàng)建線程
int pthread_create(pthread_t *thread, const pthread_attr_t* attr,void* (*start_routine)(void*), void* arg);

pthread_create 函數(shù)參數(shù)介紹

thread:線程 id 地址,pthread_t 為無符號整數(shù)
attr:線程屬性(線程優(yōu)先級)
start_routine:函數(shù)指針,執(zhí)行對應(yīng)的函數(shù)功能(可以對函數(shù)進行傳參),也被稱為回調(diào)函數(shù)
arg:是指向任意數(shù)據(jù)的指針,將參數(shù)傳遞給 start_routine 函數(shù)
返回值:線程創(chuàng)建成功返回0,失敗錯誤碼被設(shè)置

示例:

#include <iostream>
#include <pthread>
#include <unistd.h>void* thread_run(void* arg)
{while(true){std::cout << "new thread running" << std::endl;sleep(1);}return nullptr;
}int main()
{pthread_t t;pthread_create(&t, nullptr, thread_run, nullptr);//創(chuàng)建線程,t是輸出型參數(shù)//主進程while(true){std::cout << "main thread running, new thread id:" << t << std::endl;sleep(1);}return 0;
}

上面代碼直接編譯的話會出現(xiàn)鏈接報錯,這是因為這個多線程是一個庫,直接編譯 g++ 會找不到這個庫,需要指定編譯器去找線程庫。
在這里插入圖片描述

對此,在編譯時,使用 g++ 進行編譯要加上 -lpthread 選項

g++ -o threadTest threadTest .c -std=c++11 -lpthread

在這里插入圖片描述

可以通過 ldd 對編譯好的可執(zhí)行文件來查看線程庫的位置:

ldd threadTest

在這里插入圖片描述
執(zhí)行程序可以看到,主線程與子線程同時運行:

在這里插入圖片描述

在這里插入圖片描述
此時輸出的線程id會很大,很奇怪。其實這些線程的id是地址,創(chuàng)建的線程會被線程庫管理起來,形成數(shù)組,每個對應(yīng)的線程id 其實就是數(shù)組的下標。

創(chuàng)建的線程是不能確定先后順序的. Linux下的線程是輕量級的進程,進程創(chuàng)建執(zhí)行的先后順序是由調(diào)度器決定的,對此線程誰先誰后的問題也要看調(diào)度器來決定的

創(chuàng)建線程池

下面來創(chuàng)建一個線程池,讓每一個線程都執(zhí)行 thread_run 這個函數(shù),打印對應(yīng)的創(chuàng)建編號

#include <iostream>
#include <pthread>
#include <unistd.h>#define NUM 10void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(1);}return nullptr;
}int main()
{pthread_t tids[NUM];for(int i = 0; i < NUM; i++){char thname[64];snprintf(thname, sizeof(thname), "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname);//創(chuàng)建線程池,將thname傳參}//主進程while(true){std::cout << "main thread running" << std::endl;sleep(1);}return 0;
}

編譯運行:

在這里插入圖片描述

結(jié)果很不對,輸出的結(jié)果都是一樣的。

在給線程回調(diào)函數(shù)進行傳參時,傳入的是 thname 地址。thname 字符數(shù)組是屬于主線程的,屬于臨時變量。前面提到線程會共享進程中的數(shù)據(jù)。對此,每個線程都會對這個變量進行讀寫,導(dǎo)致最終顯示的結(jié)果都是一樣的。

解決方式如下:

對 thname 變量在堆上申請空間,待到回調(diào)函數(shù)使用完后對這個資源進行釋放:

void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(1);}delete name; //釋放空間return nullptr;
}int main()
{pthread_t tids[NUM];for(int i = 0; i < NUM; i++){char* thname = new char[64]; //堆上開辟空間snprintf(thname, 64, "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname);//創(chuàng)建線程池,將thname傳參}//主進程while(true){std::cout << "main thread running" << std::endl;sleep(1);}return 0;
}

編譯運行:
在這里插入圖片描述
創(chuàng)建線程前,每次對 thname 進行資源申請,回調(diào)函數(shù)之后對資源進行釋放,可以很好的避免資源共享情況發(fā)生。從結(jié)果也可以看出不同線程的執(zhí)行先后順序也是不確定的。

給線程傳入對象的指針

創(chuàng)建線程時,不僅僅只可以傳入內(nèi)置類型變量的指針,還可以傳入自定義類型變量的指針

示例:構(gòu)建 ThreadDate 類,其內(nèi)部包含線程的基本信息。在類中實現(xiàn)輸入型參數(shù)和輸出型參數(shù),方便我們獲取線程處理后的數(shù)據(jù)結(jié)果

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <ctime>#define NUM 3enum { OK=0, ERROR };struct ThreadDate
{//構(gòu)造ThreadDate(const string& name, pthread_t tid, time_t createTime, size_t top = 0):_name(name), _tid(tid), _createTime((uint64_t)createTime),_status(OK),_top(top),_result(0){}~ThreadDate(){}//成員變量//輸入型變量string _name;pthread_t _tid;uint64_t _createTime; //創(chuàng)建時間//輸出型變量int _status; //線程退出狀態(tài)size_t _top;//累加到最大值int _result;
};

下面通過實例化這個類,來演示線程中傳入對象:

int main()
{pthread_t tids[NUM];// 創(chuàng)建線程池for (int i = 0; i < NUM; i++){char *thname = new char[64];snprintf(thname, 64, "thread-%d", i + 1);//定義ThreadDate類,傳入到線程中ThreadDate* tdate = new ThreadDate(std::string(thname), i+1, time(nullptr), (100+ i * 5));pthread_create(tids + i, nullptr, thread_run, tdate); //將tdate對象進行傳參}void *ret = nullptr; // 用于保存子線程退出的信息for (size_t i = 0; i < NUM; i++){int n = pthread_join(tids[i], &ret); //傳入ret指針的地址if(n != 0) std::cerr << "pthread_join error" << std::endl;ThreadDate* td = static_cast<ThreadDate*>(ret); //指針類型轉(zhuǎn)換if(td->_status == OK) //輸出對象內(nèi)容std::cout << td->_name << " 計算的結(jié)果是: " << td->_result << " (它要計算的是[1, " << td->_top << "])" << std::endl;//釋放資源delete td;}return 0;
}

在這里插入圖片描述

線程等待 pthread_join

上面實現(xiàn)的代碼中,我們將主線程用死循環(huán)的方式,一直維持進程的運行。

如果去掉死循環(huán),線程還能繼續(xù)執(zhí)行下去嗎?

對上面的代碼進行修改:在線程被創(chuàng)建后,維持 3 秒后主進程退出

int main()
{pthread_t tids[NUM];for(int i = 0; i < NUM; i++){char* thname = new char[64]; //堆上開辟空間snprintf(thname, 64, "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname);//創(chuàng)建線程池,將thname傳參}//主進程sleep(3);return 0;
}

在這里插入圖片描述

進程是資源的申請的主體,進程退出了,不管子進程還在進行什么操作都會終止運行。

這樣會造成什么后果?

會造成資源泄漏,如果此時的線程在堆區(qū)申請了資源還沒來得及釋放,會導(dǎo)致內(nèi)存泄漏。

線程與子進程一樣,線程退出后需要被回收處理。就拿子進程來說,當(dāng)子進程退出后會處于僵尸狀態(tài),父進程如果沒有等待子進程,對子進程的僵尸狀態(tài)進行回收的話會造成資源的泄漏。

有僵尸進程,但是有沒有僵尸線程一說。與進程相似,線程退出后也會處于一種被回收的狀態(tài),沒有及時回收線程的話,也會造成內(nèi)存泄漏

對此,線程退出是需要進行等待的

下面來介紹一個函數(shù)接口:pthread_join 等待線程

 int pthread_join(pthread_t thread, void **retval);

參數(shù)介紹:

thread:等待的線程 id 號
retval:是一個指向指針的指針,用于存儲被等待線程的返回值
返回值:等待成功返回0,失敗錯誤碼被返回

對上面的代碼進行修改,寫一個等待進程的版本:

void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(1);}delete name; //釋放空間return nullptr;
}int main()
{pthread_t tids[NUM];for(int i = 0; i < NUM; i++){// char thname[64];char* thname = new char[64];// snprintf(thname, sizeof(thname), "thread-%d", i + 1);snprintf(thname, 64, "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname);//創(chuàng)建線程池,將thname傳參}for(size_t i = 0; i < NUM; i++){pthread_join(tids[i], nullptr);//等待線程}return 0;
}

有了線程等待,可以很好的避免內(nèi)存泄漏。主進程會等待所有的子線程,只有當(dāng)所有的線程都退出后才會結(jié)束整個程序的運行。

退出線程 pthread_exit

如何控制線程的退出呢?

這里還是拿進程來說,也比較好舉例(前面也說過線程是輕量級的進程)。進程退出的方式可以在main函數(shù)中使用 return 語句、在任意行代碼處調(diào)用 exit 函數(shù)。

那么線程可以使用類似的方法嗎?

先來看看 return 語句的作用,還是拿剛剛編寫的代碼來舉例。這里我們直接往死循環(huán)內(nèi)部編寫 3 秒的停頓,之后直接執(zhí)行break 語句,后續(xù)執(zhí)行 return 語句。為了方便展示,下面只展示修改的代碼:

void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(3);break;  //跳出循環(huán)}delete name; return nullptr;
}

編譯運行,來看看執(zhí)行結(jié)果:

在這里插入圖片描述
所有的線程都會打印一次,然后停頓卡住,到執(zhí)行 return 語句后所有的線程都會退出。執(zhí)行的效果也是符合我們的預(yù)期的。

下面來使用 exit 函數(shù)來測試線程退出情況,還是上面的代碼,將 break 語句換成 exit 函數(shù)

void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;exit(10); //調(diào)用exit函數(shù)}delete name; //釋放空間return nullptr;
}

下面來看看現(xiàn)象:
在這里插入圖片描述

線程池只創(chuàng)建了一部分,然后直接終止了運行。在右邊監(jiān)視 threadTest 進程也沒有任何顯示。

exit 函數(shù)退出作用是整個 threadTest 進程,當(dāng)某一子線程調(diào)用了 exit 函數(shù)的時候,就會導(dǎo)致整個進程都退出。這也是為什么會只創(chuàng)建了一些子線程,然后導(dǎo)致整個進程都結(jié)束運行了。

對此,在線程執(zhí)行流中,非必要情況下,不要輕易的調(diào)用 exit 函數(shù)。

不能使用 exit 函數(shù),但是線程庫中提供了一個API,用于退出某一線程:pthread_exit

void pthread_exit(void *retval);

參數(shù)介紹:

retval:指向線程退出狀態(tài)的指針

當(dāng)線程調(diào)用 pthread_exit 時,它會立即停止執(zhí)行,并釋放其棧空間。但是,線程的資源(如線程ID和線程屬性)直到其他線程調(diào)用 pthread_join 來回收它時才會被完全釋放。

示例:

#define NUM 3void* thread_run(void* arg)
{char* name = (char*)arg;while(true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(4);break;}delete name; //釋放空間pthread_exit(nullptr); //退出調(diào)用的線程
}int main()
{pthread_t tids[NUM];for(int i = 0; i < NUM; i++){// char thname[64];char* thname = new char[64];// snprintf(thname, sizeof(thname), "thread-%d", i + 1);snprintf(thname, 64, "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname);//創(chuàng)建線程池,將thname傳參}//等待線程for(size_t i = 0; i < NUM; i++){ pthread_join(tids[i], nullptr); }return 0;
}

這里只創(chuàng)建了三個子線程的線程池,來看看運行的效果:
在這里插入圖片描述

線程等待參數(shù) retval 與 線程退出參數(shù) retval

先來看看這兩個API的接口聲明:

int pthread_join(pthread_t thread, void **retval); //線程等待接口
void pthread_exit(void *retval); //線程退出接口

兩個函數(shù)之間的 retval 參數(shù)有關(guān)聯(lián)嗎?答案是有的。

一般創(chuàng)建進程都是為了幫助我們?nèi)ネ瓿赡承┤蝿?wù),線程也是如此,創(chuàng)建線程也是為了幫助進程完成一部分任務(wù)。進程在完成任務(wù)后正常退出,返回對應(yīng)的退出碼。當(dāng)然,進程完成到一定的任務(wù)時也會直接退出。

下面是進程退出的幾個情況:

  1. 在 main 函數(shù)中調(diào)用 return 語句,返回對應(yīng)的退出碼;
  2. 在進程中任意代碼處調(diào)用 exit 函數(shù)。當(dāng)然調(diào)用 exit 函數(shù)需要傳參,進程退出的退出碼也就是傳入exit 函數(shù)參數(shù)的值;
  3. 收到OS的終止信號

進程的退出碼、退出信號的返回,是方便我們?nèi)ゲ榭串?dāng)前進程是不是完成了指定的任務(wù)。線程也是如此,線程退出是否正常我們也要知道。對此,上面提到的 兩個 API 接口的參數(shù)作用就是用于獲取線程退出的退出信息

線程退出接口 pthread_exit 一般是用在回調(diào)函數(shù)內(nèi)部,也就是子線程中。我們可以先將 pthread_exit 功能想象成 exit 函數(shù)那般,在子線程退出后我們將子線程退出碼帶出來。

但是問題來了,為什么 pthread_exit 傳入的參數(shù)是 void* retval 一級指針?

這個要結(jié)合 pthread_join 來看:

int pthread_join(pthread_t thread, void **retval);

pthread_join 是等待線程的一個接口,會回收退出的子線程(線程的ID、線程的屬性等)。pthread_join 的 retval 是一個輸出型參數(shù)。

這里的 retval 如同在進程中調(diào)用的 wait 函數(shù)時,傳入 status 參數(shù),這個 status 也是輸出型參數(shù),會將 子進程的退出碼、退出信號帶出來。

retval 參數(shù)的作用就是將子線程的退出數(shù)據(jù)帶出來,不同的是這里是二級指針。在使用前需要定義一個指針,然后將這個指針的地址傳入 pthread_join 的 retval 參數(shù)中。在子線程調(diào)用 pthread_exit 函數(shù)時,傳出對應(yīng)的數(shù)據(jù)即可。

光說不做,假把戲。下面來看看測試案例:

void *thread_run(void *arg)
{char *name = (char *)arg;while (true){std::cout << "new thread running,thread name is:" << name << std::endl;sleep(3);break;}delete name; // 釋放空間pthread_exit((void*)1); //子線程退出,退出信息設(shè)置為1
}int main()
{pthread_t tids[NUM];for (int i = 0; i < NUM; i++){char *thname = new char[64];snprintf(thname, 64, "thread-%d", i + 1);pthread_create(tids + i, nullptr, thread_run, thname); // 創(chuàng)建線程池,將thname傳參}void *ret = nullptr; // 用于保存子線程退出的信息for (size_t i = 0; i < NUM; i++){int n = pthread_join(tids[i], &ret); //傳入ret指針的地址if(n != 0) std::cerr << "pthread_join error" << std::endl;std::cout << "子線程:thread->" << i+1 << ",退出碼為:" << (uint64_t)ret << std::endl;}return 0;
}

這里需要注意就是傳指針的問題:

定義 ret 一級指針,傳參到 pthread_join 內(nèi)部時,傳入的是 ret 指針的地址。pthread_exit 傳參需要傳入指針類型,對此上面代碼需要對 1 進行 void* 類型的強轉(zhuǎn)。在輸出子線程退出信息時,ret 是指針,經(jīng)過子線程的等待,ret內(nèi)部值已經(jīng)被設(shè)置為了除了低位的第一位為1其他全為 0 的二進制序列,在通過 uint64_t 類型強轉(zhuǎn)即可將數(shù)據(jù)打印輸出!

在這里插入圖片描述

還要提一點就是:在獲取線程的退出碼時,是不需要考慮異常的。如果一個線程中出現(xiàn)了異常,那么就會帶動的整個主進程退出。主進程都退出了還需要考慮等待進程的異常嗎?是不需要的。對此,在多線程中是不需要考慮異常的!異常問題通常是由進程來考慮。

線程中斷 pthread_cancel

在實際開發(fā)需求中,如果想要將創(chuàng)建的線程中斷運行需要用到 API:pthread_cancel

int pthread_cancel(pthread_t thread);

參數(shù)介紹:

thread:傳入的線程編號

示例:我們先來創(chuàng)建一個正常線程,再執(zhí)行一段任務(wù)后線程會自動退出:

void* thread_run(void* args)
{//靜態(tài)類型轉(zhuǎn)換const char* str = static_cast<const char*>(args);int cnt = 5;while(cnt){cout << str << "is runing :" << cnt-- << endl;sleep(1);}//退出線程pthread_exit((void*)1);
}	int main()
{//創(chuàng)建線程pthread_t tid;pthread_create(&tid, nullptr, thread_run, (void*)"thread 1");//等待線程void* ret = nullptr;pthread_join(tid, &ret);return 0;
}

在這里插入圖片描述

修改上述代碼,在線程執(zhí)行兩秒任務(wù)后,直接調(diào)用 pthread_cancel 接口,查看現(xiàn)象:

void* thread_run(void* args)
{//靜態(tài)類型轉(zhuǎn)換const char* str = static_cast<const char*>(args);int cnt = 5;while(cnt){cout << str << "is runing :" << cnt-- << endl;sleep(1);}//退出線程pthread_exit((void*)1);
}	int main()
{//創(chuàng)建線程pthread_t tid;pthread_create(&tid, nullptr, thread_run, (void*)"thread 1");//2秒后,中斷線程sleep(2);pthread_cancel(tid);//等待線程void* ret = nullptr;pthread_join(tid, &ret);return 0;
}

在這里插入圖片描述
可以看到當(dāng)線程執(zhí)行兩秒后直接中斷

獲取線程編號 pthread_self

pthread_t pthread_self(void);

誰調(diào)用這個接口就獲取誰的線程 id 編號,示例:

void* thread_run(void* args)
{//靜態(tài)類型轉(zhuǎn)換const char* str = static_cast<const char*>(args);int cnt = 5;while(cnt){cout << str << "is runing :" << cnt-- << "obtain self id ->" << pthread_self() << endl; //獲取線程idsleep(1);}//退出線程pthread_exit((void*)1);
}	int main()
{//創(chuàng)建線程pthread_t tid;pthread_create(&tid, nullptr, thread_run, (void*)"thread 1");//等待線程void* ret = nullptr;pthread_join(tid, &ret);cout << " new thread exit : " << (int64_t)ret << "quit thread: " << tid << endl;return 0;
}

在這里插入圖片描述

線程分離 pthread_detach

新線程被創(chuàng)建,默認情況下是 joinable 的,線程退出,主進程需要對這個線程進行 pthread_join 操作。不對線程進行等待的操作就會造成內(nèi)存泄漏,無法釋放資源。

如果不關(guān)心線程的返回值,那么等待就會變成一種負擔(dān)。

就是主線程自己為了等待子線程,難道不用去做自己的事情了嗎?這個時候,我們可以告訴OS,當(dāng)線程退出的時候,自己去釋放資源。如何操作呢?需要用到下面這個 API :

int pthread_detach(pthread_t thread);

pthread_detach 功能是將一個線程分離出來,但是要記住一個點:被分離的線程在后續(xù)操作是不能被等待的!!如果對被分離的線程進行 pthread_join 操作,主進程是會報錯的。報錯出現(xiàn)后,就不會再對子線程進行等待操作,直接向后運行屬于主進程的代碼

線程分離好比現(xiàn)實生活中的:已婚與未婚,是屬于一種屬性。
線程分離,并不是字面上的意思將線程與進程分離開那種。分離是一種屬性,沒有被分離的線程,是 joinable 的。該線程需要被等待回收資源;已經(jīng)被分離的線程,其內(nèi)部屬性會發(fā)生變化,表示這個線程不需要再被等待回收資源。

示例:創(chuàng)建一個子線程,在等待子線程之前對該子線程進行分離操作

#include <pthread.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <string>using namespace std;void* threadRoution(void* arg)
{const char* tname = static_cast<const char*>(arg);int cnt = 5;while(cnt){cout << tname << ":" << cnt-- << endl;sleep(1);}return nullptr;
}int main()
{//創(chuàng)建線程pthread_t tid;pthread_create(&tid, nullptr, threadRoution, (void*)"thread 1");//對子線程進行分離操作pthread_detach(tid);//等待線程void* ret = nullptr;int n = pthread_join(tid, &ret);if(n != 0) cerr << "error:" << errno << strerror(n) << endl;return 0;
}

編譯查看效果:

在這里插入圖片描述

主進程在等待子線程時,發(fā)現(xiàn)該線程已經(jīng)被分離。對此,不會再阻塞等待子線程,程序直接向后運行走,子線程也沒有機會繼續(xù)執(zhí)行對應(yīng)的功能,整個進程就退出了。

因此,線程分離的主要功能就是將子線程分離出來,讓主進程有更多的時間去處理屬于自己事情,也不需要對子線程的資源釋放與否而擔(dān)心。

不過在使用線程分離的時候,要注意執(zhí)行流先后問題,不然會出現(xiàn)奇奇怪怪的現(xiàn)象。

下面來舉個例子:在子線程內(nèi)部去調(diào)用本線程的分離

void* threadRoution(void* arg)
{//將調(diào)用的線程分離開來pthread_detach(pthread_self());const char* tname = static_cast<const char*>(arg);int cnt = 5;while(cnt){cout << tname << ":" << cnt-- << endl;sleep(1);}return nullptr;
}int main()
{//創(chuàng)建線程pthread_t tid;pthread_create(&tid, nullptr, threadRoution, (void*)"thread 1");int n = pthread_join(tid, nullptr);if(n != 0) cerr << "error:" << errno << strerror(n) << endl;return 0;
}

在這里插入圖片描述

此時會發(fā)現(xiàn),線程正常的跑,主進程也等待成功。

子線程調(diào)用分離沒有用嗎?其實不然,這是由于執(zhí)行流先后問題

子線程被創(chuàng)建出來之前,主進程就執(zhí)行到了 pthread_join 代碼處,子線程還沒有來得及分離,分離屬性沒有被修改,造成主進程阻塞等待子線程。對此,就算子線程將自己分離開來,主進程早就處于進行了等待狀態(tài),也就造成了子線程繼續(xù)往后執(zhí)行的現(xiàn)象。

提示:使用線程分離的接口,盡量在創(chuàng)建線程之后進行調(diào)用,防止奇奇怪怪的執(zhí)行流的問題產(chǎn)生

線程操作就講到這里,感謝大家的支持!!

http://www.risenshineclean.com/news/63962.html

相關(guān)文章:

  • 網(wǎng)站域名登陸長沙seo優(yōu)化價格
  • 蘇州網(wǎng)站建設(shè)推廣服務(wù)百度電話怎么轉(zhuǎn)人工客服
  • 怎么做網(wǎng)站免費的刷贊百度seo正規(guī)優(yōu)化
  • 廣州網(wǎng)站外貿(mào)推廣seo有哪些網(wǎng)站
  • 哪家手表網(wǎng)站鞏義網(wǎng)絡(luò)推廣
  • 大型網(wǎng)站開發(fā) 框架網(wǎng)絡(luò)搜索關(guān)鍵詞排名
  • 凡科做的網(wǎng)站為什么打不開十大跨界營銷案例
  • 做網(wǎng)站需要哪些素材網(wǎng)站優(yōu)化排名軟件
  • wordpress javascript廣告插件seo排名推廣
  • 網(wǎng)站做優(yōu)化多少錢牛推網(wǎng)
  • 汶上云速網(wǎng)站建設(shè)如何找做網(wǎng)站的公司
  • 北京微信網(wǎng)站建設(shè)費用北京seo優(yōu)化公司
  • 網(wǎng)站建設(shè)有什么方法連接數(shù)據(jù)庫網(wǎng)絡(luò)營銷師證
  • 政府網(wǎng)站建設(shè)新模式網(wǎng)站排名優(yōu)化軟件聯(lián)系方式
  • 開鎖都在什么網(wǎng)站做最有效的推廣學(xué)校的方式
  • 諸城做網(wǎng)站找個人種子搜索神器 bt 下載
  • 網(wǎng)站建設(shè) 價格新聞軟文自助發(fā)布平臺
  • 大連app制作seo外包優(yōu)化網(wǎng)站
  • jsp做網(wǎng)站能實現(xiàn)什么功能百度網(wǎng)盤搜索引擎
  • .網(wǎng)站開發(fā)工具dw搜索引擎付費推廣
  • .net 創(chuàng)建網(wǎng)站項目網(wǎng)絡(luò)營銷的主要特點有哪些
  • 關(guān)于網(wǎng)站建設(shè)相關(guān)文章武漢 網(wǎng)絡(luò) 推廣
  • 南京網(wǎng)站流量優(yōu)化輕松seo優(yōu)化排名 快排
  • 建設(shè)公司網(wǎng)站要注意哪些杭州網(wǎng)站排名提升
  • 化妝品網(wǎng)站建設(shè)項目計劃書今日新聞頭條
  • wordpress建站速度提升免費推廣途徑與原因
  • 深圳網(wǎng)站設(shè)計價格表優(yōu)化大師下載舊版本安裝
  • 山東德州如何網(wǎng)站建設(shè)教程qq群排名優(yōu)化
  • 廣州做和改版網(wǎng)站的公司網(wǎng)上賣貨的平臺有哪些
  • 好用的wordpress代碼編輯器河南seo外包