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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux多线程编程实例解析

發(fā)布時(shí)間:2023/12/9 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux多线程编程实例解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為 pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時(shí)需要使用庫libpthread.a。順便說一下,Linux 下pthread的實(shí)現(xiàn)是通過系統(tǒng)調(diào)用clone()來實(shí)現(xiàn)的。clone()是 Linux所特有的系統(tǒng)調(diào)用,它的使用方式類似fork,關(guān)于clone()的詳細(xì)情況,有興趣的讀者可以去查看有關(guān)文檔說明。下面我們展示一個(gè)最簡單的 多線程程序 pthread_create.c。


一個(gè)重要的線程創(chuàng)建函數(shù)原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

返回值:若是成功建立線程返回0,否則返回錯(cuò)誤的編號
形式參數(shù):
??????????????? pthread_t *restrict tidp 要創(chuàng)建的線程的線程id指針
??????????????? const pthread_attr_t *restrict attr 創(chuàng)建線程時(shí)的線程屬性
??????????????? void* (start_rtn)(void) 返回值是void類型的指針函數(shù)
??????????????? void *restrict arg?? start_rtn的行參
?????????????? ?
例程1:????????????????????????????? ?
??? 功能:創(chuàng)建一個(gè)簡單的線程
??? 程序名稱:pthread_create.c???

代碼如下:

[cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • ??
  • void?*mythread1(void)??
  • {??
  • ????int?i;??
  • ????for(i?=?0;?i?<?10;?i++)??
  • ????{??
  • ????????printf("This?is?the?1st?pthread,created?by?xiaoqiang!\n");??
  • ????????sleep(1);??
  • ????}??
  • }??
  • ??
  • void?*mythread2(void)??
  • {??
  • ????int?i;??
  • ????for(i?=?0;?i?<?10;?i++)??
  • ????{??
  • ????????printf("This?is?the?2st?pthread,created?by?xiaoqiang!\n");??
  • ????????sleep(1);??
  • ????}??
  • }??
  • ??
  • int?main(int?argc,?const?char?*argv[])??
  • {??
  • ????int?i?=?0;??
  • ????int?ret?=?0;??
  • ????pthread_t?id1,id2;??
  • ??
  • ????ret?=?pthread_create(&id1,?NULL,?(void?*)mythread1,NULL);??
  • ????if(ret)??
  • ????{??
  • ????????printf("Create?pthread?error!\n");??
  • ????????return?1;??
  • ????}??
  • ??
  • ????ret?=?pthread_create(&id2,?NULL,?(void?*)mythread2,NULL);??
  • ????if(ret)??
  • ????{??
  • ????????printf("Create?pthread?error!\n");??
  • ????????return?1;??
  • ????}??
  • ??????
  • ????pthread_join(id1,NULL);??
  • ????pthread_join(id2,NULL);??
  • ??
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?vi?thread1.c??
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread1?thread1.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread1??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?2st?pthread,created?by?xiaoqiang!??
  • This?is?the?1st?pthread,created?by?xiaoqiang!??
  • fs@ubuntu:~/qiang/thread$???
  • 兩個(gè)線程交替執(zhí)行。
    另外,因?yàn)閜thread的庫不是linux系統(tǒng)的庫,所以在進(jìn)行編譯的時(shí)候要加上-lpthread,否則編譯不過,會出現(xiàn)下面錯(cuò)誤
    thread_test.c: 在函數(shù) ‘create’ 中:
    thread_test.c:7: 警告: 在有返回值的函數(shù)中,程序流程到達(dá)函數(shù)尾
    /tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):對‘pthread_create’未定義的引用
    collect2: ld 返回 1
    此例子介紹了創(chuàng)建線程的方法

    ?

    下面例子介紹向線程傳遞參數(shù)。
    例程2:
    功能:向新的線程傳遞整形值
    程序名稱:pthread_int.c

    代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????int?*num;??
  • ????num?=?(int?*)arg;??
  • ????printf("Create?parameter?is?%d\n",*num);??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main(int?argc,?const?char?*argv[])??
  • {??
  • ????pthread_t?id1;??
  • ????int?error;??
  • ??
  • ????int?test?=?4;??
  • ????int?*attr?=?&test;??
  • ??
  • ????error?=?pthread_create(&id1,NULL,create,(void?*)attr);??
  • ??
  • ????if(error)??
  • ????{??
  • ????????printf("Pthread_create?is?not?created!\n");??
  • ????????return?-1;??
  • ????}??
  • ????sleep(1);??
  • ??
  • ????printf("Pthread_create?is?created..\n");??
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?vi?thread2.c??
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread2?thread2.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread2??
  • Create?parameter?is?4??
  • Pthread_create?is?created..??
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    ??? 可以看出來,我們在main函數(shù)中傳遞的整行指針,傳遞到我們新建的線程函數(shù)中。

    在上面的例子可以看出來我們向新的線程傳入了另一個(gè)線程的int數(shù)據(jù),線程之間還可以傳遞字符串或是更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
    例程3:
    程序功能:向新建的線程傳遞字符串
    程序名稱:pthread_string.c
    代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • ??
  • void?*create(char?*arg)??
  • {??
  • ????char?*str;??
  • ????str?=?arg;??
  • ????printf("The?parameter?passed?from?main?is?%s\n",str);??
  • ??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main()??
  • {??
  • ????int?error;??
  • ????pthread_t?id1;??
  • ????char?*str1?=?"Hello?,xiaoqiang!";??
  • ????char?*attr?=?str1;??
  • ????error?=?pthread_create(&id1,?NULL,?create,?(void?*)attr);??
  • ??
  • ????if(error?!=?0)??
  • ????{??
  • ????????printf("This?pthread?is?not?created!\n");??
  • ????????return?-1;??
  • ????}??
  • ????sleep(1);??
  • ??
  • ????printf("pthread?is?created..\n");??
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?./thread3??
  • The?parameter?passed?from?main?is?Hello?,xiaoqiang!??
  • pthread?is?created..??
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    可以看出來main函數(shù)中的字符串傳入了新建的線程中。

    例程4:
    程序功能:向新建的線程傳遞字符串
    程序名稱:pthread_struct.c

    代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<stdlib.h>??
  • ??
  • struct?menber??
  • {??
  • ????int?a;??
  • ????char?*s;??
  • };??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????struct?menber?*temp;??
  • ????temp?=?(struct?menber?*)arg;??
  • ????printf("menber->a?=?%d\n",temp->a);??
  • ????printf("menber->s?=?%s\n",temp->s);??
  • ??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main()??
  • {??
  • ????int?error;??
  • ????pthread_t?id1;??
  • ????struct?menber?*p;??
  • ????p?=?(struct?menber?*)malloc(sizeof(struct?menber));??
  • ????p->a?=?1;??
  • ????p->s?=?"xiaoqiang!";??
  • ??
  • ????error?=?pthread_create(&id1,NULL,create,(void?*)p);??
  • ??
  • ????if(error)??
  • ????{??
  • ????????printf("pthread?is?not?created!\n");??
  • ????????return?-1;??
  • ????}??
  • ????sleep(1);??
  • ????printf("pthread?is?created!\n");??
  • ??
  • ????free(p);??
  • ????p?=?NULL;??
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?vi?thread4.c??
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread4?thread4.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread4??
  • menber->a?=?1??
  • menber->s?=?xiaoqiang!??
  • pthread?is?created!??
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    ??? 可以看出來main函數(shù)中的一個(gè)結(jié)構(gòu)體傳入了新建的線程中。
    ??? 線程包含了標(biāo)識進(jìn)程內(nèi)執(zhí)行環(huán)境必須的信息。他集成了進(jìn)程中的所有信息都是對線程進(jìn)行共享的,包括文本程序、程序的全局內(nèi)存和堆內(nèi)存、棧以及文件描述符

    例程5:
    程序目的:驗(yàn)證新建立的線程可以共享進(jìn)程中的數(shù)據(jù)
    程序名稱:pthread_share.c

    代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • ??
  • static?int?a?=?5;??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????printf("New?pthread...\n");??
  • ????printf("a?=?%d\n",a);??
  • ??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main(int?argc,?const?char?*argv[])??
  • {??
  • ????int?error;??
  • ????pthread_t?id1;??
  • ??
  • ????error?=?pthread_create(&id1,?NULL,?create,?NULL);??
  • ????if(error?!=?0)??
  • ????{??
  • ????????printf("new?thread?is?not?created!\n");??
  • ????????return?-1;??
  • ????}??
  • ????sleep(1);??
  • ????printf("New?thread?is?created...\n");??
  • ??
  • ????return?0;??
  • }??
  • 結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?vi?thread5.c??
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread5?thread5.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread5??
  • New?pthread...??
  • a?=?5??
  • New?thread?is?created...??
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    可以看出來,我們在主線程更改了我們的全局變量a的值的時(shí)候,我們新建立的線程則打印出來了改變的值,可以看出可以訪問線程所在進(jìn)程中的數(shù)據(jù)信息。

    2、線程的終止
    如果進(jìn)程中任何一個(gè)線程中調(diào)用exit,_Exit,或者是_exit,那么整個(gè)進(jìn)程就會終止,
    與此類似,如果信號的默認(rèn)的動作是終止進(jìn)程,那么,把該信號發(fā)送到線程會終止進(jìn)程。
    線程的正常退出的方式:
    (1) 線程只是從啟動例程中返回,返回值是線程中的退出碼
    (2) 線程可以被另一個(gè)進(jìn)程進(jìn)行終止
    (3) 線程自己調(diào)用pthread_exit函數(shù)

    兩個(gè)重要的函數(shù)原型:

    [cpp]?view plaincopy
  • include?<pthread.h>??
  • void?pthread_exit(void?*rval_ptr);??
  • /*rval_ptr?線程退出返回的指針*/??
  • ??
  • int?pthread_join(pthread_t?thread,void?**rval_ptr);??
  • ???/*成功結(jié)束進(jìn)程為0,否則為錯(cuò)誤編碼*/??
  • pthread_join使一個(gè)線程等待另一個(gè)線程結(jié)束。 代碼中如果沒有pthread_join主線程會很快結(jié)束從而使整個(gè)進(jìn)程結(jié)束,從而使創(chuàng)建的線程沒有機(jī)會開始執(zhí)行就結(jié)束了。加入pthread_join后,主線程會一直等待直到等待的線程結(jié)束自己才結(jié)束,使創(chuàng)建的線程有機(jī)會執(zhí)行。 頭文件 : #include <pthread.h> 函數(shù)定義: int pthread_join(pthread_t thread, void **retval); 描述 :pthread_join()函數(shù),以阻塞的方式等待thread指定的線程結(jié)束。當(dāng)函數(shù)返回時(shí),被等待線程的資源被收回。如果線程已經(jīng)結(jié)束,那么該函數(shù)會立即返回。并且thread指定的線程必須是joinable的。 參數(shù) :thread: 線程標(biāo)識符,即線程ID,標(biāo)識唯一線程。retval: 用戶定義的指針,用來存儲被等待線程的返回值。 返回值 : 0代表成功。 失敗,返回的則是錯(cuò)誤號。

    ?

    例程6
    程序目的:線程正常退出,接受線程退出的返回碼
    程序名稱:pthread_exit.c
    執(zhí)行代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<unistd.h>??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????printf("new?thread?is?created?...?\n");??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main(int?argc,char?*argv[])??
  • {??
  • ????pthread_t?tid;??
  • ????int?error;??
  • ????void?*temp;??
  • ??
  • ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
  • ??
  • ????if(?error?)??
  • ????{??
  • ????????printf("thread?is?not?created?...?\n");??
  • ????????return?-1;??
  • ????}??
  • ????error?=?pthread_join(tid,?&temp);??
  • ??
  • ????if(?error?)??
  • ????{??
  • ????????printf("thread?is?not?exit?...?\n");??
  • ????????return?-2;??
  • ????}??
  • ??
  • ????printf("thread?is?exit?code?%d?\n",?(int?)temp);??
  • ??????????????????????????????????????????
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?vi?thread6.c??
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread6?thread6.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread6??
  • new?thread?is?created?...???
  • thread?is?exit?code?0???
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    可以看出來,線程退出可以返回線程的int數(shù)值。

    線程退出不僅僅可以返回線程的int數(shù)值,還可以返回一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)

    例程7
    程序目的:線程結(jié)束返回一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
    代碼如下: [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<unistd.h>??
  • ??
  • struct?menber??
  • {??
  • ????int?a;??
  • ????char?*b;??
  • }temp={8,"xiaoqiang"};??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????printf("new?thread?...?\n");??
  • ????return?(void?*)&temp;??
  • }??
  • ??
  • int?main(int?argc,char?*argv[])??
  • {??
  • ????int?error;??
  • ????pthread_t?tid;??
  • ????struct?menber?*c;??
  • ??
  • ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
  • ??
  • ????if(?error?)??
  • ????{??
  • ????????printf("new?thread?is?not?created?...?\n");??
  • ????????return?-1;??
  • ????}??
  • ????printf("main?...?\n");??
  • ??
  • ????error?=?pthread_join(tid,(void?*)&c);??
  • ??
  • ????if(?error?)??
  • ????{??
  • ????????printf("new?thread?is?not?exit?...?\n");??
  • ????????return?-2;??
  • ????}??
  • ????printf("c->a?=?%d??\n",c->a);??
  • ????printf("c->b?=?%s??\n",c->b);??
  • ????sleep(1);??
  • ????return?0;??
  • }??
  • 執(zhí)行結(jié)果如下: [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread7?thread7.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread7??
  • main?...???
  • new?thread?...???
  • c->a?=?8????
  • c->b?=?xiaoqiang????
  • fs@ubuntu:~/qiang/thread$???
  • 例程總結(jié):
    一定要記得返回的數(shù)據(jù)結(jié)構(gòu)要是在這個(gè)數(shù)據(jù)要返回的結(jié)構(gòu)沒有釋放的時(shí)候應(yīng)用,如果數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生變化,那返回的就不會是我們所需要的,而是臟數(shù)據(jù)。 3、線程標(biāo)識
    ????? 函數(shù)原型: #include <pthread.h>
    pthread_t pthread_self(void);
    pid_t getpid(void);
    ??? getpid()用來取得目前進(jìn)程的進(jìn)程識別碼,函數(shù)說明

    例程8
    程序目的:實(shí)現(xiàn)在新建立的線程中打印該線程的id和進(jìn)程id
    代碼如下: [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<pthread.h>??
  • #include?<unistd.h>?/*getpid()*/??
  • ??
  • void?*create(void?*arg)??
  • {??
  • ????printf("New?thread?....?\n");??
  • ????printf("This?thread's?id?is?%u??\n",?(unsigned?int)pthread_self());??
  • ????printf("The?process?pid?is?%d??\n",getpid());??
  • ????return?(void?*)0;??
  • }??
  • ??
  • int?main(int?argc,char?*argv[])??
  • {??
  • ????pthread_t?tid;??
  • ????int?error;??
  • ??
  • ????printf("Main?thread?is?starting?...?\n");??
  • ??
  • ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
  • ??
  • ????if(error)??
  • ????{??
  • ????????printf("thread?is?not?created?...?\n");??
  • ????????return?-1;??
  • ????}??
  • ????printf("The?main?process's?pid?is?%d??\n",getpid());??
  • ????sleep(1);??
  • ????return?0;??
  • }??
  • <span?style="font-family:Arial;BACKGROUND-COLOR:?#ffffff"></span>??
  • 執(zhí)行結(jié)果如下: [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/thread$?gcc?-o?thread8?thread8.c?-lpthread??
  • fs@ubuntu:~/qiang/thread$?./thread8??
  • Main?thread?is?starting?...???
  • The?main?process's?pid?is?4955????
  • New?thread?....???
  • This?thread's?id?is?3075853120????
  • The?process?pid?is?4955????
  • fs@ubuntu:~/qiang/thread$?
  • 總結(jié)

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

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