国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

減肥養(yǎng)生網(wǎng)站建設自制網(wǎng)站教程

減肥養(yǎng)生網(wǎng)站建設,自制網(wǎng)站教程,一家專門做原產(chǎn)地的網(wǎng)站,地區(qū)汽車修理網(wǎng)站建設本篇我將學習如何使用多線程。要使用多線程,因為Linux沒有給一般用戶直接提供操作線程的接口,我們使用的接口,都是系統(tǒng)工程師封裝打包成原生線程庫中的。那么就需要用到原生線程庫。因此,需要引入-lpthread,即連接原生…

本篇我將學習如何使用多線程。要使用多線程,因為Linux沒有給一般用戶直接提供操作線程的接口,我們使用的接口,都是系統(tǒng)工程師封裝打包成原生線程庫中的。那么就需要用到原生線程庫。因此,需要引入-lpthread,即連接原生線程庫。

原生線程庫:#include <pthread.h>
自動化構建工具:
mythread:mythread.cgcc -o $@ $^ -lpthread
.PHONY:clean
clean:rm -f mythread

創(chuàng)建線程

創(chuàng)建線程。

功能:創(chuàng)建一個新的線程
原型:int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*(*start_routine)(void*), void* arg);
參數(shù):
thread : 返回線程ID.
attr : 設置線程的屬性,attr為NULL表示使用默認屬性.
start_routine : 是個函數(shù)地址,線程啟動后要執(zhí)行的函數(shù).
arg : 傳給線程啟動函數(shù)的參數(shù).
返回值:成功返回0;失敗返回錯誤碼.

獲取調用它的線程id。即哪個線程調用了它,就能夠獲得自己的id。

函數(shù)原型:pthread_t pthread_self(void);
功能:獲取一個線程id,即誰調用它,就獲取誰的線程id
頭文件:#include <pthread.h>
參數(shù):無
返回值:成功返回這個id。這個函數(shù)總是成功的!

創(chuàng)建一個線程,代碼如下:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_run(void *args)
{while(1){//使用pthread_self()獲取idprintf("我是新線程[%s],我的線程ID是: %lu\n",(const char*)args,pthread_self());sleep(1);}
}int main()
{pthread_t tid;//第一個參數(shù)為線程id,第二個為線程屬性,設置為NULL默認值//第三個參數(shù)是線程執(zhí)行的方法,第四個是傳給第三個參數(shù)的參數(shù)pthread_create(&tid,NULL,thread_run,(void*)"new thread");while(1){printf("我是主線程,我創(chuàng)建的線程ID是: %lu,我的線程ID是: %lu\n",tid,pthread_self());sleep(1);}return 0;
}

結果如下,能看到兩個線程的ID不一樣,那就證明了單個進程中存在著兩個線程。?

?創(chuàng)建多個線程,代碼如下:

使用數(shù)組來存放線程id。注意此時thread_run()函數(shù)被重入了!

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_run(void *args)
{while(1){//使用pthread_self()獲取id// printf("我是新線程[%s],我創(chuàng)建的線程ID是: %lu\n",(const char*)args,pthread_self());sleep(3);}
}int main()
{//創(chuàng)建五個線程,保存在數(shù)組中pthread_t tid[5];//第一個參數(shù)為線程id,第二個為線程屬性,設置為NULL默認值//第三個參數(shù)是線程執(zhí)行的方法,第四個是傳給第三個參數(shù)的參數(shù)int i = 0;for(i = 0;i<5;++i){pthread_create(tid+1,NULL,thread_run,(void*)"new thread");}while(1){printf("我是主線程,我的thread ID:%lu\n",pthread_self());printf("######################begin########################\n");for(i = 0;i<5;++i){  printf("我是主線程,我創(chuàng)建的線程[%d]ID是: %lu,我的線程ID是: %lu\n",i,tid[i],pthread_self());}printf("######################end######################\n");sleep(1);}return 0;
}

結果如下:?

通過ps -aL查看當前線程??梢钥吹?#xff0c;PID和LWP相同的就是主線程,其它的都是新線程。LWP是線程id。

線程等待

一般而言,線程也是需要等待的,如果不等待,就可能會導致類似于"僵尸進程"的問題。

功能:等待線程結束
原型:int pthread_join(pthread_t thread, void** value_ptr);
參數(shù):
thread : 線程ID
value_ptr : 它指向一個指針,后者指向線程的返回值
返回值:成功返回0;失敗返回錯誤碼

寫一個簡單的測試,主線程在等待,10秒后打印111.

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_run(void *args)
{int num = *(int*)args;while(1){//使用pthread_self()獲取idprintf("我是新線程[%d],我創(chuàng)建的線程ID是: %lu\n",num,pthread_self());sleep(10);break;}//隨便返回一個值用于測試return (void*)111;
}#define NUM 1
int main()
{pthread_t tid[NUM];int i = 0;for(i = 0;i<NUM;++i){pthread_create(tid+1,NULL,thread_run,(void*)&i);sleep(1);}//指針變量可以當某個數(shù)據(jù)的容器void *status = NULL;//獲得退出信息pthread_join(tid[0],&status);printf("ret: %d\n",(int)status);return 0;
}

線程只能一個個等。

線程終止

線程終止的方案有:

1.函數(shù)中的return。對于這個方案有兩種情況:第一種情況是在main函數(shù)中的return,此時代表進程和主線程都退出了。第二種情況是其它函數(shù)中的return,代表該線程的退出。

2.使用函數(shù)pthread_exit().

功能:線程終止
原型:void pthread_exit(void* value_ptr);
參數(shù):
value_ptr : z指的是退出后的返回值,也就是return X。value_ptr不要指向一個局部變量。
返回值:無返回值,跟進程一樣,線程結束的時候無法返回到它的調用者(自身)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_run(void *args)
{int num = *(int*)args;while(1){//使用pthread_self()獲取idprintf("我是新線程[%d],我創(chuàng)建的線程ID是: %lu\n",num,pthread_self());sleep(2);break;}pthread_exit((void*)123);
}#define NUM 1
int main()
{    pthread_t tid[NUM];int i = 0;for(i = 0;i<NUM;++i){pthread_create(tid+1,NULL,thread_run,(void*)&i);sleep(1);}//指針變量可以當某個數(shù)據(jù)的容器void *status = NULL;//獲得退出信息pthread_join(tid[0],&status);printf("ret: %d\n",(int)status);return 0;
}

如果使用exit(),那么會將進程和全部線程都終止掉。

需要注意,pthread_exit或者return返回的指針所指向的內存單元必須是全局的或者是用malloc分配的,不能在線程函數(shù)的棧上分配,因為當其它線程得到這個返回指針時線程函數(shù)已經(jīng)退出了,函數(shù)退出代表函數(shù)棧幀被銷毀,從而這個內存單元也被銷毀了。

3.使用pthread_cancel函數(shù)取消目標線程。

功能:取消一個執(zhí)行中的線程
原型:int pthread_cancel(pthread_t thread);
參數(shù):
thread : 線程ID
返回值:成功返回0;失敗返回錯誤碼,退出碼為-1
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_run(void *args)
{int num = *(int*)args;while(1){//使用pthread_self()獲取idprintf("我是新線程[%d],我創(chuàng)建的線程ID是: %lu\n",num,pthread_self());sleep(2);//break;}//pthread_exit((void*)123);//隨便返回一個值用于測試//return (void*)111;
}#define NUM 1
int main()
{pthread_t tid[NUM];int i = 0;for(i = 0;i<NUM;++i){pthread_create(tid+1,NULL,thread_run,(void*)&i);sleep(1);}printf("wait sub thread...\n");//等5秒鐘sleep(5);printf("cancel sub thread...\n");//取消線程pthread_cancel(tid[0]);//指針變量可以當某個數(shù)據(jù)的容器void *status = NULL;//獲得退出信息pthread_join(tid[0],&status);printf("ret: %d\n",(int)status);return 0;
}

當一個新線程被取消后,退出碼為-1,即PTHREAD_ CANCELED。

當把主線程取消,但新線程沒有被取消,此時新線程依舊在運行著,并且主線程會進入"僵尸狀態(tài)"(說明:線程沒有僵尸狀態(tài)這個東東,是有類似僵尸進程的問題)。因此我們一般不能用新線程去取消主線程。

線程分離

默認情況下,新創(chuàng)建的線程是joinable的,線程退出后,需要對其進行pthread_join操作,否則無法釋放資源,從而造成系統(tǒng)泄漏。

如果不關心線程的返回值,join是一種負擔,這個時候,我們可以告訴系統(tǒng),當線程退出時,自動釋放線程資源。

線程分離后,不需要被join終止,只需運行結束后會自動釋放Z。分離后的線程相對于是同一屋檐下的陌生人,即這個線程在跟同一個進程內的線程毫無關系了,此時一定不能對其join,因為會失敗。

可以是線程組內其他線程對目標線程進行分離,也可以是線程自己分離。

線程分離一般的應用場景是主線程不退出,新線程處理完任務后退出。

功能:分離線程
原型:int pthread_detach(pthread_t thread);
參數(shù):
thread : 線程ID
返回值:成功返回0;
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>void *thread_run(void *args)
{//分離pthread_detach(pthread_self());int num = *(int*)args;while(1){//使用pthread_self()獲取idprintf("我是新線程[%d],我創(chuàng)建的線程ID是: %lu\n",num,pthread_self());sleep(2);break;}//隨便返回一個值用于測試return (void*)111;
}#define NUM 1
int main()
{pthread_t tid[NUM];int i = 0;for(i = 0;i<NUM;++i){pthread_create(tid+1,NULL,thread_run,(void*)&i);sleep(1);}printf("wait sub thread...\n");//等5秒鐘sleep(5);printf("cancel sub thread...\n");//指針變量可以當某個數(shù)據(jù)的容器void *status = NULL;int ret = 0;//獲得退出信息ret = pthread_join(tid[0],&status);printf("ret: %d,status: %d\n",ret,(int)status);return 0;
}

LPW的解釋

在使用ps -aL查看線程情況時,LWP為內核LWP,我們最好不要叫它線程ID,因為在Linux中沒有線程這玩意,我們所說的線程,都是進程PCB模擬出來的,屬于輕量級進程。

對于LWP,它的值跟我們在測試代碼時得出的結果(線程的ID)不一樣,一個是原生線程庫的,一個是內核的。

下面將好好分析一下,原生線程庫中的"線程pid"的本質。

先來說結果,我們通過pthread_self()獲取的線程id,其實是虛擬內存地址!

我們都知道,每一個線程都要有運行的臨時數(shù)據(jù),因此每個線程都要有自己的私有棧結構!也需要擁有描述線程的用戶控制塊!但是在虛擬地址空間中的棧結構,不可能會分成很多份給每一個線程的,它是屬于主線程和進程的!

每一個新線程所擁有的棧結構等等,其實都是由原生線程庫提供的!每一個線程跟每一個庫提供的線程棧和線程局部存儲等組成的用戶控制塊都是一一對應的,是以1:1的比例對對應著!

那么如何區(qū)找到需要找到的線程,就需要用到一個地址去找,并且每一個描述線程的用戶控制塊都會保存著每一個線程對應的PWD!這個地址就是每一個用戶控制塊的地址!

總結:

①pthread_ create函數(shù)會產(chǎn)生一個線程ID,存放在第一個參數(shù)指向的地址中。該線程ID和內核LWP不是一回事,前者是原生線程庫中的,一個是內核LWP。
②前面講的LWP(線程ID)屬于進程調度的范疇。因為線程是輕量級進程,是操作系統(tǒng)調度器的最小單位,所以需要一個數(shù)值來唯一表示該線程。
③pthread_ create函數(shù)第一個參數(shù)指向一個虛擬內存單元,該內存單元的地址即為新創(chuàng)建線程的線程ID,屬于NPTL線程庫的范疇。線程庫的后續(xù)操作,就是根據(jù)該線程ID來操作線程的。
④線程庫NPTL提供了pthread_ self函數(shù),可以獲得線程自身的ID。

http://m.aloenet.com.cn/news/37816.html

相關文章:

  • 衡水建設投資集團網(wǎng)站萬能軟文范例800字
  • 網(wǎng)站加載頁模板太倉seo網(wǎng)站優(yōu)化軟件
  • 那個網(wǎng)站專做地質基礎信息域名查詢服務器
  • 網(wǎng)站在工信部備案百度seo優(yōu)化招聘
  • 網(wǎng)站為什么不被收錄網(wǎng)絡營銷工具包括
  • 3建設營銷型網(wǎng)站流程圖生成關鍵詞的軟件免費
  • 基于web前端的旅游網(wǎng)站論文自己做一個網(wǎng)站需要多少錢
  • 北京網(wǎng)站制作公司興田德潤可信賴網(wǎng)絡營銷主要學什么
  • 企業(yè)網(wǎng)站建設方案價位企業(yè)網(wǎng)站設計服務
  • 網(wǎng)站制作的困難和解決方案成都推廣系統(tǒng)
  • 蘇州驚天網(wǎng)站制作網(wǎng)想要推廣網(wǎng)頁正式版
  • 山東威海網(wǎng)站開發(fā)關鍵詞推廣排名
  • 做網(wǎng)站被捉域名注冊優(yōu)惠
  • 大型門戶網(wǎng)站有哪些石家莊網(wǎng)絡推廣優(yōu)化
  • 賺錢軟件真實可靠揭陽市seo上詞外包
  • 時光軸 網(wǎng)站sem是什么電鏡
  • 免費淘寶客網(wǎng)站模板seo優(yōu)化需要做什么
  • 嘉祥網(wǎng)站建設中國數(shù)據(jù)網(wǎng)
  • 網(wǎng)站都有什么類型清遠頭條新聞
  • 微信團購網(wǎng)站怎么做seo資源
  • 網(wǎng)站輪播廣告動畫怎么做南京最大網(wǎng)站建設公司
  • 更新網(wǎng)站要怎么做呢鏈接交換
  • 米課做網(wǎng)站軟文素材庫
  • 怎樣免費做網(wǎng)站視頻講解網(wǎng)絡服務電話
  • 已有網(wǎng)站做app需要多少錢寧波谷歌seo推廣
  • 北京網(wǎng)站設計制作教程滄浪seo網(wǎng)站優(yōu)化軟件
  • 哪里有網(wǎng)站建設加盟合作今日新聞最新頭條
  • wordpress所有文章網(wǎng)站排名優(yōu)化推廣
  • 上海整站優(yōu)化公司網(wǎng)絡營銷理論
  • 網(wǎng)站建設與文字的工作成都百度推廣代理公司