色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

什么是多線程編程?Linux下的多線程編程

Linux大陸 ? 來源:Linux大陸 ? 作者:Linux大陸 ? 2023-05-06 10:58 ? 次閱讀

什么是多線程編程

1、線程和進程的區別

進程是指正在運行的程序,它擁有獨立的內存空間和系統資源,不同進程之間的數據不共享。

線程是進程內的執行單元,它與同一進程內的其他線程共享進程的內存空間和系統資源。

2、多線程的優勢和應用場景

多線程是一種并發編程方式,它的優勢包括:

提高程序的響應速度和運行效率(多核CPU下的多線程)

充分利用CPU資源,提高系統的利用率

支持多個任務并行執行,提高程序的可擴展性和可維護性

Linux下的多線程編程

Linux下C語言多線程編程依賴于pthread多線程庫。pthread庫是Linux的多線程庫,是POSIX標準線程API的實現,它提供了一種創建和操縱線程的方法,以及一些同步機制,如互斥鎖、條件變量等。

頭文件:

#include

編譯鏈接需要鏈接鏈接庫 pthread。

一、線程的基本操作

1、pthread_create

/**
*@brief創建一個線程
*
*Detailedfunctiondescription
*
*@param[in] thread:一個指向線程標識符的指針,線程調用后,該值被設置為線程ID;pthread_t為unsigned long int
*@param[in]attr:用來設置線程屬性
*@param[in]start_routine:線程函數體,線程創建成功后,thread指向的內存單元從該地址開始運行
*@param[in]arg:傳遞給線程函數體的參數
*
*@return線程創建成功,則返回0,失敗則返回錯誤碼,并且thread內容是未定義的
*/
intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),void*arg);

例子test.c:創建一個線程,每1s打印一次。

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;

void*thread_fun(void*arg)
{
s_thread_running=1;
while(s_thread_running)
{
printf("threadrun...
");
sleep(1);
}

pthread_exit(NULL);
}

intmain(void)
{
intret=0;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

ret=pthread_join(s_thread_id,NULL);///

編譯、運行:

gcctest.c-otest-lpthread
83b7cd30-ebb9-11ed-90ce-dac502259ad0.png

2、pthread_join

/**
*@brief等待某個線程結束
*
*Detailedfunctiondescription:這是一個線程阻塞函數,調用該函數則等到線程結束才繼續運行
*
*@param[in]thread:某個線程的ID
*@param[in]retval:用于獲取線程start_routine的返回值
*
*@return線程創建成功,則返回0,失敗則返回錯誤碼,并且thread內容是未定義的
*/
intpthread_join(pthread_tthread,void**retval);

例子test.c:創建一個線程,進行一次加法運算就返回。

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;

void*thread_fun(void*arg)
{
staticintres=0;
inta=1,b=2;

res=a+b;
sleep(1);
printf("threadrun,a+b=%d,addr=%p
",res,&res);

pthread_exit(&res);
}

intmain(void)
{
intret=0;
int*retval=NULL;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("pthread_createerror!
");
exit(EXIT_FAILURE);
}

ret=pthread_join(s_thread_id,(void**)&retval);///

編譯、運行:

83c09d52-ebb9-11ed-90ce-dac502259ad0.png

3、pthread_exit

/**
*@brief退出線程
*
*Detailedfunctiondescription
*
*@param[in]retval:它指向的數據將作為線程退出時的返回值
*
*@returnvoid
*/
voidpthread_exit(void*retval);

線程將指定函數體中的代碼執行完后自行結束;

線程執行過程中,被同一進程中的其它線程(包括主線程)強制終止;

線程執行過程中,遇到 pthread_exit() 函數結束執行。

例子test.c:創建一個線程,每個1s打印一次,打印超過5次時調用pthread_exit退出。

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;
conststaticchar*thread_exit_str="thread_exitok!";

void*thread_fun(void*arg)
{
staticintcnt=0;

s_thread_running=1;
while(s_thread_running)
{
cnt++;
if(cnt>5)
{
pthread_exit((void*)thread_exit_str);
}
printf("threadrun...
");
sleep(1);
}

pthread_exit(NULL);
}

intmain(void)
{
intret=0;
void*thread_res=NULL;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

ret=pthread_join(s_thread_id,(void**)&thread_res);
if(ret!=0)
{
printf("thread_joinerror!
");
exit(EXIT_FAILURE);
}
printf("AfterThread,thread_res=%s
",(char*)thread_res);
exit(EXIT_SUCCESS);
}

編譯、運行:

83ceb22a-ebb9-11ed-90ce-dac502259ad0.png

使用return退出線程與使用pthread_exit退出線程的區別?

return為通用的函數退出操作,pthread_exit專用與線程,既然pthread庫有提供專門的函數,自然用pthread_exit會好些,雖然使用return也可以。

看看return退出線程與使用pthread_exit退出線程的具體區別:退出主線程。使用pthread_exit退出主線程只會終止當前線程,不會影響進程中其它線程的執行;使用return退出主線程,主線程退出執行很快,所有線程都會退出。

例子:使用pthread_exit退出主線程

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;
conststaticchar*thread_exit_str="thread_exitok!";

void*thread_fun(void*arg)
{
sleep(1);
printf("thread_funrun...
");
pthread_exit(NULL);
}

intmain(void)
{
intret=0;
void*thread_res=NULL;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

printf("mainthreadexit
");
pthread_exit(NULL);
}

編譯、運行:

83d7f89e-ebb9-11ed-90ce-dac502259ad0.png

例子:使用return退出主線程

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;
conststaticchar*thread_exit_str="thread_exitok!";

void*thread_fun(void*arg)
{
sleep(1);
printf("thread_funrun...
");
pthread_exit(NULL);
}

intmain(void)
{
intret=0;
void*thread_res=NULL;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

printf("mainthreadexit
");

return0;
}

編譯、運行:

83e03c8e-ebb9-11ed-90ce-dac502259ad0.png

4、pthread_self

/**
*@brief用來獲取當前線程ID
*
*Detailedfunctiondescription
*
*@param[in]void
*
*@return返回線程id
*/
pthread_tpthread_self(void);

例子:

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;
conststaticchar*thread_exit_str="thread_exitok!";

void*thread_fun(void*arg)
{
staticintcnt=0;

s_thread_running=1;
while(s_thread_running)
{
cnt++;
if(cnt>5)
{
pthread_exit((void*)thread_exit_str);
}
printf("threadrun(tid=%ld)...
",pthread_self());
sleep(1);
}

pthread_exit(NULL);
}

intmain(void)
{
intret=0;
void*thread_res=NULL;

pid_tpid=getpid();
printf("pid=%d
",pid);

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

ret=pthread_join(s_thread_id,(void**)&thread_res);
if(ret!=0)
{
printf("thread_joinerror!
");
exit(EXIT_FAILURE);
}
printf("AfterThread,thread_res=%s
",(char*)thread_res);
exit(EXIT_SUCCESS);
}

編譯、運行:

83eb089e-ebb9-11ed-90ce-dac502259ad0.png

5、pthraad_detach

/**
*@brief分離線程
*
*Detailedfunctiondescription:分離線程,線程結束是系統自動回收線程的資源
*
*@param[in]thread:某個線程的ID
*
*@return成功時返回0,失敗返回其他值
*/
intpthread_detach(pthread_tthread);

pthread_create創建的線程有兩種狀態:joinable(可結合的)和unjoinable(不可結合的/分離的)。默認是joinable 狀態。

一個可結合的線程能夠被其他線程收回其資源和殺死;在被其他線程回收之前,它的存儲器資源(如棧)是不釋放的,所以以默認的屬性創建線程時,創建的線程時可結合的,我們需要對線程退出時調用pthread_join對線程資源進行回收。只有當pthread_join函數返回時,創建的線程才算終止,才能釋放自己占用的系統資源。

一個不可結合的線程,線程結束后會自動釋放占用資源。

因為pthread_join是一個阻塞的操作,而大多數時候主線程并不希望因為調用pthread_join而阻塞,并且大多數情況下不會使用線程函數體的返回值,所以這時候可以把線程創建為不可結合的/分離的。

把線程創建為不可結合的/分離的有兩種方式:

在創建線程之后,使用pthraad_detach分離線程。

在創建線程之前,使用pthread_attr_setdetachstate設置線程以不可結合的/分離的狀態創建。

例子:在創建線程之后,使用pthraad_detach分離線程。

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;

void*thread_fun(void*arg)
{
s_thread_running=1;
while(s_thread_running)
{
printf("childthreadrun...
");
sleep(1);
}

pthread_exit(NULL);
}

intmain(void)
{
intret=0;

printf("BeforeThread
");
ret=pthread_create(&s_thread_id,NULL,thread_fun,NULL);
if(ret!=0)
{
printf("thread_createerror!
");
exit(EXIT_FAILURE);
}

ret=pthread_detach(s_thread_id);
if(ret!=0)
{
printf("pthread_detacherror!
");
exit(EXIT_FAILURE);
}
printf("AfterThread
");

while(1)
{
printf("mainthreadrun...
");
sleep(1);
}

exit(EXIT_SUCCESS);
}

編譯、運行:

83f4b81c-ebb9-11ed-90ce-dac502259ad0.png

pthread_join與pthraad_detach的區別:

pthread_detach()即主線程與子線程分離,兩者相互不干涉,子線程結束同時子線程的資源自動回收。

pthread_join()即是子線程合入主線程,主線程會一直阻塞,直到子線程執行結束,然后回收子線程資源,并繼續執行。

6、pthread_attr_init

/**
*@brief初始化一個線程對象的屬性
*
*Detailedfunctiondescription
*
*@param[in]attr:指向一個線程屬性的指針
*
*@return成功時返回0,失敗返回其他值
*/
intpthread_attr_init(pthread_attr_t*attr);

如果不設置線程屬性,線程則以默認屬性進行創建,默認的屬性值如:

83ff653c-ebb9-11ed-90ce-dac502259ad0.png

例子:在創建線程之前,使用pthread_attr_setdetachstate設置線程以不可結合的/分離的狀態創建。

#include
#include
#include
#include

staticpthread_ts_thread_id;
staticunsignedchars_thread_running=0;

void*thread_fun(void*arg)
{
s_thread_running=1;
while(s_thread_running)
{
printf("threadrun...
");
sleep(1);
}

pthread_exit(NULL);
}

intmain(void)
{
intret=0;

printf("BeforeThread
");
pthread_attr_tattr;
ret=pthread_attr_init(&attr);
if(ret!=0)
{
printf("pthread_attr_initerror!
");
exit(EXIT_FAILURE);
}
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);///

二、互斥鎖(mutex)的使用

互斥鎖用于保護一些公共資源。一些公共資源有可能會被多個線程共同使用,如果不做資源保護,可能會產生意想不到的bug。

一個線程,如果需要訪問公共資源,需要獲得互斥鎖并對其加鎖,資源在在鎖定過程中,如果其它線程對其進行訪問,也需要獲得互斥鎖,如果獲取不到,線程只能進行阻塞,直到獲得該鎖的線程解鎖。

互斥鎖API:

#include
///

互斥鎖有兩種創建方式:

靜態創建:

pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;

動態創建:

pthread_mutex_tmutex;
pthread_mutex_init(&mutex,NULL);

pthread互斥鎖屬性包括:

PTHREAD_MUTEX_TIMED_NP:這是缺省值,也就是普通鎖。當一個線程加鎖以后,其余請求鎖的線程將會形成一個等待隊列,并在解鎖后按優先級獲得鎖。這種策略可以確保資源分配的公平性。

PTHREAD_MUTEX_RECURSIVE_NP:嵌套鎖。允許同一個線程對同一個鎖成功獲得多次,并通過unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭。

PTHREAD_MUTEX_ERRORCHECK_NP:檢錯鎖。如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同,這樣就保證了當不允許多次加鎖時不會出現最簡單情況下的死鎖。

PTHREAD_MUTEX_ADAPTIVE_NP:適應鎖,動作最簡單的鎖類型,僅等待一小段時間,如果不能獲得鎖就放棄等待

互斥鎖使用形式:

pthread_mutex_tmutex;
pthread_mutex_init(&mutex,NULL);///

例子:

#include
#include
#include
#include

staticpthread_ts_thread1_id;
staticpthread_ts_thread2_id;
staticunsignedchars_thread1_running=0;
staticunsignedchars_thread2_running=0;

staticpthread_mutex_ts_mutex;
staticints_cnt=0;

void*thread1_fun(void*arg)
{
printf("[%s]pthread_mutex_lock------s_cnt=%d
",__FUNCTION__,s_cnt);
pthread_mutex_lock(&s_mutex);///

編譯、運行:

84066468-ebb9-11ed-90ce-dac502259ad0.png

三、條件變量的使用

條件變量是在線程中以睡眠的方式等待某一條件的發生,是利用線程間共享的全局變量進行同步的一種機制。

條件變量是線程可用的一種同步機制,條件變量給多個線程提供了一個會合的場所,條件變量與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發生。

條件變量API:

#include
///

假如有兩個線程,線程1依賴于某個變量才能執行相應的操作,而這個變量正好是由線程2來改變的。這種情況下有兩種方案編寫程序:

方案一:線程1輪詢的方式檢測這個變量是否變化,變化則執行相應的操作。

方案二:使用條件變量的方式。線程1等待線程2滿足條件時進行喚醒。

其中,方案一比較浪費CPU資源。

條件變量的例子:創建兩個線程,線程1對全局計數變量cnt從0開始進行自增操作。線程2打印5的倍數,線程1打印其它數。

#include
#include
#include
#include

staticpthread_ts_thread1_id;
staticpthread_ts_thread2_id;
staticunsignedchars_thread1_running=0;
staticunsignedchars_thread2_running=0;

staticpthread_mutex_ts_mutex;
staticpthread_cond_ts_cond;
staticints_cnt=0;

void*thread1_fun(void*arg)
{
s_thread1_running=1;
while(s_thread1_running)
{
pthread_mutex_lock(&s_mutex);///

編譯、運行:

8415bce2-ebb9-11ed-90ce-dac502259ad0.png






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11319

    瀏覽量

    209830
  • C語言
    +關注

    關注

    180

    文章

    7608

    瀏覽量

    137111
  • 編程
    +關注

    關注

    88

    文章

    3627

    瀏覽量

    93809
  • gcc編譯器
    +關注

    關注

    0

    文章

    78

    瀏覽量

    3399

原文標題:Hello系列 | 多線程編程基礎!

文章出處:【微信號:Linux大陸,微信公眾號:Linux大陸】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux多線程編程手冊

    Linux多線程編程手冊
    發表于 11-07 10:17

    嵌入式Linux多線程編程

    嵌入式Linux多線程編程-學習資源-華清遠見清遠見嵌入式學院:清遠見嵌入式學院:《嵌入式應用程序設計》——第5 章 嵌入式Linux 多線程
    發表于 11-05 06:54

    QNX環境多線程編程

    介紹了QNX 實時操作系統和多線程編程技術,包括線程間同步的方法、多線程程序的分析步驟、線程基本程序結構以及實用編譯方法。QNX 是由加拿大
    發表于 08-12 17:37 ?30次下載

    linux多線程編程課件

    電子發燒友為您提供了linux多線程編程課件,希望對您學習 linux 有所幫助。部分內容如下: *1、多線程模型在單處理器模型和多處理器系
    發表于 07-10 11:58 ?0次下載

    linux多線程編程開發

    本文中我們針對 Linux多線程編程的主要特性總結出 5 條經驗,用以改善 Linux 多線程編程
    發表于 12-26 14:24 ?55次下載
    <b class='flag-5'>linux</b><b class='flag-5'>多線程</b><b class='flag-5'>編程</b>開發

    MFC多線程編程

    計算機上的上位機制作工具語言之MFC多線程編程
    發表于 09-01 14:55 ?0次下載

    VC-MFC多線程編程詳解

    VC編程中關于 MFC多線程編程的詳解文檔
    發表于 09-01 15:01 ?0次下載

    Windows多線程編程

    計算機上的上位機制作工具語言之Windows多線程編程,感興趣的可以看看。
    發表于 09-01 15:27 ?0次下載

    linux多線程編程技術

    (process)中只允許有一個線程,這樣多線程就意味著多進程。現在,多線程技術已經被許多操作系統所支持,包括Windows/NT,當然,也包括Linux。 為什么有了進程的概念后,還
    發表于 10-24 16:01 ?5次下載

    什么是多線程編程?多線程編程基礎知識

    摘要:多線程編程是現代軟件技術中很重要的一個環節。要弄懂多線程,這就要牽涉到多進程。本文主要以多線程編程以及
    發表于 12-08 16:30 ?1.3w次閱讀

    關于Linux多線程編程技術學習總結

    Linux多線程編程技術 作為一個IT人員,不斷的學習和總結是我們這個職業習慣,所以我會將每個階段的學習都會通過一點的總結來記錄和檢測自己的學習效果,今天為大家總結了關于
    發表于 04-22 03:12 ?2211次閱讀
    關于<b class='flag-5'>Linux</b><b class='flag-5'>下</b><b class='flag-5'>多線程</b><b class='flag-5'>編程</b>技術學習總結

    Linux多線程編程

    的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。  下面我們先來嘗試編寫一個簡單的多線程程序。2 簡單的多線程編程  
    發表于 04-02 14:43 ?610次閱讀

    Linux多線程編程的知識點

    Hello、Hello大家好,我是木榮,今天我們繼續來聊一聊Linux多線程編程中的重要知識點,詳細談談多線程中同步和互斥機制。
    發表于 04-26 17:27 ?607次閱讀
    <b class='flag-5'>Linux</b>中<b class='flag-5'>多線程</b><b class='flag-5'>編程</b>的知識點

    mfc多線程編程實例

    (圖形用戶界面)應用程序的開發。在這篇文章中,我們將重點介紹MFC中的多線程編程多線程編程在軟件開發中非常重要,它可以實現程序的并發執行,提高程序的效率和響應速度。MFC提供了豐富
    的頭像 發表于 12-01 14:29 ?1521次閱讀

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可
    的頭像 發表于 11-12 14:16 ?397次閱讀
    主站蜘蛛池模板: 野花韩国视频中文播放| 116美女写真午夜电影z| 人妻免费久久久久久久了| 暖暖视频免费观看社区| 欧美xxxxxbb| 欧美成人中文字幕在线视频| 农民下乡在线观看3| 日韩欧美高清一区| 天津相声广播在线收听| 校园纯肉H教室第一次| 亚洲色播永久网址大全| 在线中文高清资源免费观看| 99成人在线视频| 动漫成人片| 国产偷国产偷亚州清高| 精品夜夜澡人妻无码AV蜜桃| 美女裸露100%奶头视频| 青青青青久久久久国产的| 玩弄朋友娇妻呻吟交换电影| 亚洲一区综合图区| 91极品蜜桃臀在线播放| 成人高清网站| 果冻传媒视频在线观看完整版免费| 久久国产一区二区三区| 欧美精品专区免费观看| 网址在线观看你懂我意思吧免费的| 亚洲精品无码葡京AV天堂 | 初中XXXXXL| 国产色精品VR一区二区| 久久人妻少妇嫩草AV蜜桃35I| 欧美亚洲国产激情一区二区| 午夜AV内射一区二区三区红桃视| 一品道门免费高清视频| sm主人调教揉花蒂H| 国产精品无码AV天天爽人妻蜜桃 | 一本道高清无码v| 99久久久无码国产精品免费人妻| 国产电影午夜成年免费视频| 久久re热在线视频精69| 日本69xx 老师| 亚洲综合色五月久久婷婷|