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

歡迎訪問 生活随笔!

生活随笔

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

linux

linux posix 线程池_linux多线程--POSIX Threads Programming

發(fā)布時間:2023/12/2 linux 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux posix 线程池_linux多线程--POSIX Threads Programming 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

linux多線程自己從接觸很久也有不少實踐,但總是覺得理解不夠深刻,不夠系統(tǒng)。借這篇文章試著再次系統(tǒng)學(xué)習(xí)一下linux多線程編程,理解編程的concept,細致看一下POSIX pthread API的實現(xiàn)。還是憑借強大的google search,找到幾篇不錯的文章和教程附在最后。我在這篇文章中的總結(jié)大多都是基于這些材料的學(xué)習(xí)和自己實踐經(jīng)驗的一點總結(jié)。

Thread基本知識

Process 地址空間

Thread附著在process內(nèi)部,先看一下process在CPU上是個什么樣的吧。啟動一個linux process,OS會開辟一塊內(nèi)存用來裝載code,保存data和process狀態(tài)。看一下進程的地址空間。

根據(jù)訪問權(quán)限,進程地址空間分為user space和kernel space。32bit系統(tǒng)中高1G為kernel space,低3G為user space,具體劃分為:

Process control block(從高1G kernel space中分配)

stack

memory mapping segment

heap

bss and data

text

1G的kernel space是這臺機器上所有processes共享的,每個進程的PCB存在這個空間中,一般應(yīng)用程序是沒有辦法直接訪問修改的,但是kernel 通過/proc 提供給應(yīng)用程序一個接口可以查看PCB的信息,部分內(nèi)容還可以修改,詳細可以看一下/proc。剩下的stack/heap/text/...都駐留在process user space,是屬于process私有空間。詳細的kernel如何管理進程memory還可以再開一篇。

Thread是什么?

process是個重型的運行實體,以process為單位切分任務(wù)和調(diào)度,os的開銷太大了。我們可以把process這個單位再切小些,thread的概念就誕生了。好,我們來看一下怎樣把這個單位切小的。簡單來講,thread共享大部分的process的內(nèi)容,只維護必需的一小部分作為私有內(nèi)容。

Thread自己維護的私有內(nèi)容

Kernel space

Stack pointer

Registers

Scheduling properties (such as policy or priority)

Set of pending and blocked signals

Thread specific data.

User space

stack

其他諸如PCB中進程信息,用戶空間中的text/data/heap/...都是同一個process下所有Threads共享的。有了這些thread自己私有的信息,os就可以以thread為單位去調(diào)度了。因為它是輕量級的,所以相比process,thread一般具有更好的性能,更快的響應(yīng)速度。但是thread的穩(wěn)定性和編程復(fù)雜度要比process差些,要考慮的內(nèi)容比較多。

Threads通信和同步

正因為同一個process內(nèi)的threads間天然共享了大量的內(nèi)存,thread間的信息交互要比較高效,同時也增加了復(fù)雜度,總要處理好共享內(nèi)存間的互斥。當(dāng)然process間也可以共享內(nèi)存,比如通過進程父子關(guān)系,或者通過/dev/shm mmap特定物理內(nèi)存到進程空間內(nèi)或者其他。

線程間通信

所有的IPC(inter process communication)方法都適用于thread間的通信。比較全的IPC總結(jié),可以參考IPC。比較常用的我們會涉及到message queue,sharememory,semaphore,socket,signal等。semaphore是共享資源互斥的方法,其他都是冗余的方式進行通信。互斥是個比較復(fù)雜的話題,我們單開一節(jié)討論一下。

共享資源的互斥

為什么要保護共享資源做互斥訪問,這里不羅嗦了。通過對共享資源(臨界區(qū))加鎖可以實現(xiàn)互斥訪問,互斥鎖(mutex)也有多種類型。

simple blocking

一方拿到臨界區(qū)鎖后,其它人再來拿鎖都會掛起。

Recursive(遞歸型)

允許鎖的擁有者多次申請鎖而不被掛起,對遞歸調(diào)用有用。

Reader/Writer

允許多個reader同時share讀鎖,如果有reader在讀,writer申請鎖會block直到所有reader釋放。可以理解為一寫多讀,寫時互斥。這種鎖有寫?zhàn)I死的風(fēng)險。

其中POSIX的pthread庫支持recursive和reader/writer類型的鎖。

共享訪問帶來的風(fēng)險和挑戰(zhàn)

共享訪問中有寫操作,必然要考慮互斥。互斥有風(fēng)險,使用需謹慎。如果你最終不可避免的要使用互斥鎖,要關(guān)注互斥鎖的這些風(fēng)險。

deadlock(死鎖)

死鎖一般發(fā)生在雙方或者多方在申請兩個以上的互斥鎖,然后大家各拿了部分,互不相讓。開發(fā)者要盡量避免這種編程場景發(fā)生,如果真的需要可以編程要么同時獲得,要么一個都不要,做人要有骨氣!

race condition(競爭條件)

共享資源在沒有互斥機制保護時,由于線程調(diào)度的不確定性會導(dǎo)致共享的資源變化無序無規(guī)律,程序的輸出也就不確定了。共享資源無互斥保護,線程間競爭訪問,輸出無法保證。這要求開發(fā)者要特別小心識別出程序中的那些共享資源,加鎖保護。尤其是第三方的開源軟件,多線程調(diào)用時要注意是否是線程安全的。

priority reversion(優(yōu)先級反轉(zhuǎn))

優(yōu)先級反轉(zhuǎn)是個很有意思的問題,尤其是在嵌入式實時OS上,進程/線程的調(diào)度是搶占式的,高優(yōu)先級的任務(wù)ready時可以直接搶占CPU,這事再加上互斥就容易出問題了。比如三個任務(wù)H,M,L,優(yōu)先級遞減,同時H和L共享資源R。當(dāng)L先申請到互斥鎖訪問臨界區(qū)還沒釋放R的時候,H這時候申請R訪問導(dǎo)致自己掛起,這么巧M變ready了,OS調(diào)度讓M搶占了L的cpu。如果L一直得不到執(zhí)行并釋放R,這樣就造成了高優(yōu)先級的H得不到執(zhí)行,反而一些比H優(yōu)先級低的M們能得到CPU。這就是優(yōu)先級反轉(zhuǎn)。實時OS的高優(yōu)先級任務(wù)一般都是比較重要的任務(wù)需要馬上處理,得不到處理意味著可能要出大事。所以這個問題的影響還是挺大的,比較著名的例子就是火星探路者的故事,可以參考一下火星探路者故障分析。解決方法也有不少

盡量避免不同優(yōu)先級的任務(wù)共享資源,可以通過信息容易做任務(wù)間通信。

訪問臨界區(qū)時關(guān)閉中斷,保證臨界區(qū)的代碼執(zhí)行不被強占。嵌入式編程中常用。

優(yōu)先級繼承,當(dāng)有高優(yōu)先級任務(wù)想要訪問共享資源時,提高正在執(zhí)行的低優(yōu)先級任務(wù)的優(yōu)先級到高優(yōu)先級級別直至退出臨界區(qū)。上面的探路者修正程序使用了該方法。

隨機提高ready且持有鎖的任務(wù)優(yōu)先級,windows用了該方法。

Multi Threads應(yīng)用場景

寫了這么多,那到底什么時候可以應(yīng)用多線程來解決問題呢?根據(jù)經(jīng)驗,一般下面一些場景我們可以考慮使用多線程。

多核處理器,任務(wù)比較容易切分為并行處理的小塊。如果是計算密集型的,線程數(shù)量可以考慮跟core的數(shù)量相當(dāng)。

有delay比較多的IO操作,可以考慮將IO的操作分離給單獨的線程。

有人機交互和實時響應(yīng)等實時性要求較高任務(wù),可以考慮分離為優(yōu)先級較高的線程。

有大量實時要求不高的計算,可以考慮分離為優(yōu)先級較低的后臺任務(wù)。

Thread編程模型

實事求是,具體問題具體分析是放之四海而皆準的問題解決之道,所以沒有普適的編程模型。下面列舉3種應(yīng)用比較多的模型以供學(xué)習(xí)。

Thread Pool (Master/Worker)

通過線程池維護一組可用的線程,master作為主線程負責(zé)管理維護worker線程,同時負責(zé)對外接口和工作的分發(fā)。

Peer (Workcrew)

跟master/worker類似,只是master在啟動線程池后退化為普通一員,大家一起分擔(dān)任務(wù),沒有主從的星形拓撲結(jié)構(gòu)。

Pipeline

跟CPU的pipline技術(shù)類似,將一個工作流分成很多串行的部分,每一部分都由不同的線程負責(zé),大家各司其職,我做完我的工作就轉(zhuǎn)交給下一個線程,齊心協(xié)力最后完成整個工作。流水線如果拍的好可以很好的提高工作效率,但是這種模型風(fēng)險也比較大,一定要處理好工作的切分,和線程間的交互。

POSIX API詳解

Thread management

pthread_create (thread,attr,start_routine,arg) #創(chuàng)建thread

pthread_exit (status) # thread退出

pthread_cancel (thread) # 退出指定的thread

pthread_attr_init (attr) #初始化thread屬性

pthread_attr_destroy(attr)

pthread_setaffinity_np or sched_setaffinity # 設(shè)置thread可運行的CPU,也就是綁定CPU

pthread_join (threadid,status) # 阻塞等待threadid指定的thread完成

pthread_detach (threadid) # 線程創(chuàng)建默認是joinable,調(diào)用該函數(shù)設(shè)置線程的狀態(tài)為detached,則該線程運行結(jié)束后會自動釋放所有資源,別人再join等待它時候不會阻塞了。

pthread_attr_setdetachstate (attr,detachstate)

pthread_attr_getdetachstate (attr,detachstate)

pthread_self () # 返回自己所在的線程id

pthread_equal (thread1,thread2) # 比較兩個線程

大部分API見名思意比較簡單,詳細看一下pthread_create.

#include

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

參數(shù)說明:

thread: 指針,所指向的內(nèi)存存儲新創(chuàng)建thread的屬性,返回給caller來標識該線程

attr: thread的配置參數(shù)集

start_routine: thread創(chuàng)建后執(zhí)行的處理函數(shù),thread的主體

arg: start_routine的入?yún)?/p>

功能說明:

創(chuàng)建thread API,成功后返回0. 創(chuàng)建的thread跟創(chuàng)建者是平行關(guān)系,沒有等級繼承關(guān)系。

thread有以下屬性

Detached or joinable state

Scheduling inheritance

Scheduling policy

Scheduling parameters

Scheduling contention scope

Stack size

Stack address

Stack guard (overflow) size

Mutexes

pthread_mutex_init (mutex,attr) # 動態(tài)生成一個mutex變量

pthread_mutex_destroy (mutex) # 釋放mutex變量

pthread_mutexattr_init (attr) # 設(shè)置mutex屬性

pthread_mutexattr_destroy (attr)

pthread_mutex_lock (mutex) # lock操作,如果mutex已經(jīng)lock調(diào)用者會阻塞

pthread_mutex_trylock (mutex) # 嘗試lock,非阻塞調(diào)用

pthread_mutex_unlock (mutex) # unlock操作

Condition variables

pthread_cond_init (condition,attr)

pthread_cond_destroy (condition)

pthread_condattr_init (attr)

pthread_condattr_destroy (attr)

pthread_cond_wait (condition,mutex) # 調(diào)用者阻塞直到condition條件成立,注意調(diào)用者阻塞時會自動釋放mutex,喚醒時會自動lock mutex。調(diào)用前確保lock mutex,調(diào)用后確保調(diào)用unlock mutex

pthread_cond_signal (condition) # 通知對方條件滿足,調(diào)用前確保lock mutex,調(diào)用后確保調(diào)用unlock mutex

pthread_cond_broadcast (condition)

條件變量是另外一種線程間同步的方式,其實是一種掛起和喚醒的通信方式。可以理解為定義一個條件變量定義了一個線程間的通信通道,wait這個變量一方其實是在等待有人在這個通道上發(fā)個信號來,如果沒有人發(fā)信號他就一直阻塞掛起。它需要跟mutex配合使用,直接通過一個例子感受一下。條件變量的存在就是讓wait的這一方睡起來直到有人通知它條件滿足可以起來干活了,否則沒有條件變量只用mutex做同步,這個wait的一方需要不斷的查詢是否條件滿足,低效浪費。

#include

#include

#include

#define NUM_THREADS 3

#define TCOUNT 10

#define COUNT_LIMIT 12

int count = 0;

pthread_mutex_t count_mutex;

pthread_cond_t count_threshold_cv;

void *inc_count(void *t)

{

int i;

long my_id = (long)t;

for (i=0; i < TCOUNT; i++) {

pthread_mutex_lock(&count_mutex);

count++;

/*

Check the value of count and signal waiting thread when condition is reached. Note that this occurs while mutex is locked.

*/

if (count == COUNT_LIMIT) {

printf("inc_count(): thread %ld, count = %d Threshold reached. ",

my_id, count);

pthread_cond_signal(&count_threshold_cv);

printf("Just sent signal.\n");

}

printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",

my_id, count);

pthread_mutex_unlock(&count_mutex);

/* Do some work so threads can alternate on mutex lock */

sleep(1);

}

pthread_exit(NULL);

}

void *watch_count(void *t)

{

long my_id = (long)t;

printf("Starting watch_count(): thread %ld\n", my_id);

/*

Lock mutex and wait for signal. Note that the pthread_cond_wait routine

will automatically and atomically unlock mutex while it waits.

Also, note that if COUNT_LIMIT is reached before this routine is run by

the waiting thread, the loop will be skipped to prevent pthread_cond_wait

from never returning.

*/

pthread_mutex_lock(&count_mutex);

while (count < COUNT_LIMIT) {

printf("watch_count(): thread %ld Count= %d. Going into wait...\n", my_id,count);

pthread_cond_wait(&count_threshold_cv, &count_mutex);

printf("watch_count(): thread %ld Condition signal received. Count= %d\n", my_id,count);

printf("watch_count(): thread %ld Updating the value of count...\n", my_id,count);

count += 125;

printf("watch_count(): thread %ld count now = %d.\n", my_id, count);

}

printf("watch_count(): thread %ld Unlocking mutex.\n", my_id);

pthread_mutex_unlock(&count_mutex);

pthread_exit(NULL);

}

int main(int argc, char *argv[])

{

int i, rc;

long t1=1, t2=2, t3=3;

pthread_t threads[3];

pthread_attr_t attr;

/* Initialize mutex and condition variable objects */

pthread_mutex_init(&count_mutex, NULL);

pthread_cond_init (&count_threshold_cv, NULL);

/* For portability, explicitly create threads in a joinable state */

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

pthread_create(&threads[0], &attr, watch_count, (void *)t1);

pthread_create(&threads[1], &attr, inc_count, (void *)t2);

pthread_create(&threads[2], &attr, inc_count, (void *)t3);

/* Wait for all threads to complete */

for (i = 0; i < NUM_THREADS; i++) {

pthread_join(threads[i], NULL);

}

printf ("Main(): Waited and joined with %d threads. Final value of count = %d. Done.\n",

NUM_THREADS, count);

/* Clean up and exit */

pthread_attr_destroy(&attr);

pthread_mutex_destroy(&count_mutex);

pthread_cond_destroy(&count_threshold_cv);

pthread_exit (NULL);

}

Synchronization

pthread_rwlock_destroy

pthread_rwlock_init

pthread_rwlock_rdlock

pthread_rwlock_timedrdlock

pthread_rwlock_timedwrlock

pthread_rwlock_tryrdlock

pthread_rwlock_trywrlock

pthread_rwlock_unlock

pthread_rwlock_wrlock

pthread_rwlockattr_destroy

pthread_rwlockattr_getpshared

pthread_rwlockattr_init

pthread_rwlockattr_setpshared

上面提到的讀寫鎖。允許多個reader同時share讀鎖,如果有reader在讀,writer申請鎖會block直到所有reader釋放。

總結(jié)

以上是生活随笔為你收集整理的linux posix 线程池_linux多线程--POSIX Threads Programming的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 黄色免费成人 | 日日夜夜撸撸 | 久久日韩| 国产精品一二三四 | 日本免费一区二区三区四区五六区 | 婷婷开心激情网 | 三上悠亚三级 | 国产超碰97 | 黄色片大全 | 亚洲一区二区三区免费在线观看 | 天天操天天干天天 | 欧美一区二区三区粗大 | 68日本xxxxxⅹxxx59| 动漫玉足吸乳羞免费网站玉足 | 一区二区三区视频免费看 | 99热这里只有精品首页 | 在线观看视频亚洲 | 凹凸精品一区二区三区 | 99欧美 | 中国女人av | 久久国产精品电影 | 欧美h网站 | 性欧美日本 | 久久久久久久99 | www,xxx69 japan| 91精品国自产在线观看 | 天堂中文在线官网 | 亚洲精品四区 | 韩国三级在线 | 女人扒开屁股让男人捅 | 亚洲天堂小说 | 日本美女啪啪 | 亚洲精品国产精品乱码视色 | 成人国产av一区二区三区 | 久久久久久久久久久久久女国产乱 | 久久综合激情网 | 国产精品自拍99 | 黄色在线视频网站 | 久久伊人免费 | 少妇看片 | 欧美日韩中文字幕一区二区三区 | 尤物在线观看视频 | 一区二区三区视频网 | 夜夜天天干 | 国产天天综合 | 欧美高清视频一区二区 | 在线小视频你懂的 | 爱逼综合 | 亚洲免费a | av男人网 | 伊人草草| 天堂久久精品忘忧草 | 亚洲第一视频网站 | 国产精品一区二区精品 | 蜜臀免费av | 毛片基地免费 | 日本男女啪啪 | 人体私拍套图hdxxxx | 国产伦理久久精品久久久久 | 被两个男人吃奶三p爽文 | 午夜免费福利在线观看 | 欧美另类日韩 | 魔性诱惑 | 色成人综合网 | 三上悠亚久久精品 | 好吊色一区二区 | 国产jk精品白丝av在线观看 | 欧美一区二区三区爱爱 | 蜜臀在线一区二区三区 | 欧美一级视频免费观看 | 最近中文字幕av | 都市激情亚洲 | 熟妇高潮一区二区三区 | 亚洲成人精品一区二区三区 | 秋霞午夜网 | 久草欧美 | 国产在线视频第一页 | 最新99热 | 久久五月视频 | 国产一区欧美 | 欧美视频一区二区在线 | 欧美日本激情 | 色婷婷久久 | 国产区在线视频 | 欧美激情免费视频 | 午夜精 | 色干综合 | 精品久久999 | 精品国产三级a∨在线 | 亚洲天堂一区二区在线 | 91成人免费在线观看视频 | 日本精品影院 | 华丽的外出在线 | 蜜桃视频在线观看www | 99热这里只有精品18 | 亚洲国产第一区 | 男人深夜影院 | 今天最新中文字幕mv高清 | 欧美性猛交xxx乱大交3蜜桃 |