了解 POISX Thread

什么是 POSIX Threads

????POSIX Threads (通常被縮寫為 Pthreads)是 POSIX (可移植操作系統(tǒng)接口怖糊,Portable Operating System Interface)的線程標準,定義了創(chuàng)建和操作線程的一套 API

Pthreads

????實現(xiàn) POSIX 線程標準的庫常被稱作 PthreadsPthreads 定義了一套 C 語言的類型、函數(shù)與常量,它以 pthread.h 頭文件和一個線程庫實現(xiàn)。

Pthreads API 中大致共有 100個 函數(shù)調(diào)用蚁鳖,全都以 pthread_頭,并可以分為以下四類:

  • 線程管理赁炎,例如創(chuàng)建線程醉箕,等待(join)線程,查詢線程狀態(tài)等甘邀。
  • 互斥鎖(Mutex):創(chuàng)建琅攘、摧毀、鎖定松邪、解鎖坞琴、設置屬性等操作
  • 條件變量(Condition Variable):創(chuàng)建、摧毀逗抑、等待剧辐、通知、設置與查詢屬性等操作
  • 使用了互斥鎖的線程間的同步管理

數(shù)據(jù)類型

pthread_t

????pthread_t 是線程句柄邮府。出于可移植目的荧关,不能把它作為整數(shù)處理,應使用函數(shù) pthread_equal() 對兩個線程 id 進行比較褂傀。獲取自身所在線程 id 使用函數(shù)為 pthread_self()忍啤。

pthread_attr_t

????pthread_attr_t 是線程屬性。主要包括 scope屬性仙辟、detach屬性同波、堆棧地址、堆棧大小叠国、優(yōu)先級未檩。主要屬性的意義如下:

  • __detachstate,表示新線程是否與進程中其他線程脫離同步粟焊。

    • 設置為PTHREAD_CREATE_DETACHED冤狡, 則新線程不能用pthread_join() 來同步孙蒙,且在退出時自行釋放所占用的資源。
    • 默認為 PTHREAD_CREATE_JOINABLE悲雳】媛停可以在線程創(chuàng)建并運行以后用pthread_detach() 來設置
    • 設置為 PTHREAD_CREATE_DETACHED 狀態(tài),不論是創(chuàng)建時設置還是運行時設置怜奖,則不能再恢復到 PTHREAD_CREATE_JOINABLE 狀態(tài)浑测。
  • __schedpolicy,表示新線程的調(diào)度策略歪玲,默認值為 SCHED_OTHER,后兩種調(diào)度策略僅對超級用戶有效掷匠,運行時可以用過 pthread_setschedparam() 來改變

    • SCHED_OTHER滥崩,正常、非實時
    • SCHED_RR讹语,實時钙皮、輪轉(zhuǎn)法
    • SCHED_FIFO,實時顽决、先入先出
  • __schedparam短条,一個 struct sched_param 結(jié)構(gòu),目前僅有一個 sched_priority 整型變量表示線程的運行優(yōu)先級才菠。這個參數(shù)僅當調(diào)度策略為實時(即 SCHED_RRSCHED_FIFO )時才有效茸时,并可以在運行時通過 pthread_setschedparam() 函數(shù)來改變,默認為0赋访。系統(tǒng)支持的最大和最小的優(yōu)先級值可以用函數(shù) sched_get_priority_maxsched_get_priority_min 得到可都。

  • __inheritsched ,默認為 PTHREAD_EXPLICIT_SCHED蚓耽。

    • PTHREAD_EXPLICIT_SCHED 表示新線程使用顯式指定調(diào)度策略和調(diào)度參數(shù)(即attr中的值)渠牲,
    • PTHREAD_INHERIT_SCHED而后者表示繼承調(diào)用者線程的值。
  • __scope步悠,表示線程間競爭CPU的范圍签杈,也就是說線程優(yōu)先級的有效范圍

    • PTHREAD_SCOPE_SYSTEM鼎兽,表示與系統(tǒng)中所有線程一起競爭CPU時間答姥,
    • PTHREAD_SCOPE_PROCESS 后者表示僅與同進程中的線程競爭CPU。

pthread_barrier_t

????同步屏障數(shù)據(jù)類型

pthread_mutex_t

????pthread_mutex_t 是線程互斥鎖數(shù)據(jù)類型接奈,有兩種方法創(chuàng)建互斥鎖:

  • 靜態(tài)方式
    POSIX 定義了一個宏 PTHREAD_MUTEX_INITIALIZER 來靜態(tài)初始化互斥鎖踢涌,

  • 動態(tài)方式
    采用 pthread_mutex_init() 函數(shù)來初始化互斥鎖,其中 mutexattr 用于指定互斥鎖屬性序宦,如果為 NULL 則使用默認屬性:

    int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t*mutexattr) 
    

pthread_mutexattr_t

????互斥鎖的屬性 pthread_mutexattr_t 在創(chuàng)建鎖的時候指定睁壁,不同的鎖類型在試圖對一個已經(jīng)被鎖定的互斥鎖加鎖時表現(xiàn)不同。在 iOS 中有以下幾個類型可選:

  • PTHREAD_MUTEX_NORMAL
    這是默認值,也就是普通鎖潘明。當一個線程加鎖以后行剂,其余請求鎖的線程將形成一個等待隊列,并在解鎖后按優(yōu)先級獲得鎖钳降。這種鎖策略保證了資源分配的公平性厚宰。
  • PTHREAD_MUTEX_ERRORCHECK
    檢錯鎖,如果同一個線程請求同一個鎖遂填,則返回EDEADLK铲觉。
  • PTHREAD_MUTEX_RECURSIVE
     嵌套鎖,允許同一個線程對同一個鎖成功獲得多次吓坚,并通過多次 unlock 解鎖撵幽。如果是不同線程請求,則在加鎖線程解鎖時重新競爭礁击。

pthread_cond_t

???? pthread_cond_t 是條件變量數(shù)據(jù)類型盐杂,條件變量和互斥鎖一樣,都有靜態(tài)和動態(tài)兩種創(chuàng)建方式哆窿,

  • 靜態(tài)方式
    使用 PTHREAD_COND_INITIALIZER 常量進行初始化

  • 動態(tài)方式
    調(diào)用 pthread_cond_init() 函數(shù)

操作線程函數(shù)

創(chuàng)建一個線程

int pthread_create(pthread_t _Nullable * _Nonnull __restrict,
  const pthread_attr_t * _Nullable __restrict,
  void * _Nullable (* _Nonnull)(void * _Nullable),
  void * _Nullable __restrict);

終止當前線程

pthread_exit(void)

中斷一個線程

int pthread_cancel(pthread_t)

阻塞當前的線程

阻塞當前的線程链烈,直到另外一個線程運行結(jié)束

int pthread_join(pthread_t , void * _Nullable * _Nullable)
  __DARWIN_ALIAS_C(pthread_join);

向指定ID的線程發(fā)送一個信號

????向指定ID的線程發(fā)送一個信號,如果線程不處理該信號挚躯,則按照信號默認的行為作用于整個進程强衡。信號值0為保留信號,作用是根據(jù)函數(shù)的返回值判斷線程是不是還活著秧均。

int pthread_kill(pthread_t threadId,int signal);

線程屬性函數(shù)

初始化線程屬性變量

int pthread_attr_init(pthread_attr_t *);

設置/獲取線程屬性變量的 detachstate 屬性

int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);

設置/獲取 scope

int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_getscope(const pthread_attr_t * __restrict, int * __restrict);

設置/獲取 schedparam

int pthread_attr_setschedparam(pthread_attr_t * __restrict,
  const struct sched_param * __restrict);
int pthread_attr_getschedparam(const pthread_attr_t * __restrict,
  struct sched_param * __restrict);

銷毀線程屬性

int pthread_attr_destroy(pthread_attr_t *);

互斥鎖函數(shù)

初始化互斥鎖

  int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t*mutexattr) 

銷毀互斥鎖

int pthread_mutex_destroy(pthread_mutex_t *);

加鎖

int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_trylock(pthread_mutex_t *);

解鎖

int pthread_mutex_unlock(pthread_mutex_t *);

條件變量函數(shù)

初始化條件變量

int pthread_cond_init(
  pthread_cond_t * __restrict,
  const pthread_condattr_t * _Nullable __restrict)
  __DARWIN_ALIAS(pthread_cond_init);

銷毀條件變量

int pthread_cond_destroy(pthread_cond_t *);

等待條件變量的特殊條件發(fā)生

????pthread_cond_wait() 必須與一個 pthread_mutex 配套使用食侮。該函數(shù)調(diào)用實際上依次做了3件事:

  1. 對當前 pthread_mutex 解鎖
  2. 把當前線程掛起到當前條件變量的線程隊列
  3. 被其它線程的信號喚醒后對當前 pthread_mutex 申請加鎖。
int pthread_cond_wait(pthread_cond_t * __restrict,
  pthread_mutex_t * __restrict) __DARWIN_ALIAS_C(pthread_cond_wait);

發(fā)送一個信號

????pthread_cond_signal 發(fā)送一個信號給正在當前條件變量的線程隊列中處于阻塞等待狀態(tài)的線程目胡,使其脫離阻塞狀態(tài)锯七,喚醒后繼續(xù)執(zhí)行。如果沒有線程處在阻塞等待狀態(tài)誉己,pthread_cond_signal 也會成功返回眉尸。一般只給一個阻塞狀態(tài)的線程發(fā)信號。假如有多個線程正在阻塞等待當前條件變量巨双,則根據(jù)各等待線程優(yōu)先級的高低確定哪個線程接收到信號開始繼續(xù)執(zhí)行噪猾。如果各線程優(yōu)先級相同,則根據(jù)等待時間的長短來確定哪個線程獲得信號筑累。但 pthread_cond_signal 在多處理器上可能同時喚醒多個線程袱蜡,當只能讓一個被喚醒的線程處理某個任務時,其它被喚醒的線程就需要繼續(xù) wait慢宗。

int pthread_cond_signal(pthread_cond_t *);

工具函數(shù)

查詢線程自身線程標識號

pthread_t pthread_self(void);

比較兩個線程標識

int pthread_equal(pthread_t _Nullable, pthread_t _Nullable);

執(zhí)行一次

某些需要僅執(zhí)行一次的函數(shù)坪蚁。其中第一個參數(shù)為 pthread_once_t 類型奔穿,是內(nèi)部實現(xiàn)的互斥鎖,保證在程序全局僅執(zhí)行一次敏晤。

int pthread_once(pthread_once_t *, void (* _Nonnull)(void));

線程私有存儲(Thread-local storage贱田,簡寫 tls)

Thread-local storage 是操作系統(tǒng)為線程單獨提供的私有空間,只有有限的容量嘴脾。通常通過 pthread 庫中的函數(shù)實現(xiàn):

創(chuàng)建 key

分配用于標識進程中線程特定數(shù)據(jù)的 pthread_key_t 類型的鍵

int pthread_key_create(pthread_key_t *, void (* _Nullable)(void *));

銷毀現(xiàn)有線程特定數(shù)據(jù) Key

int pthread_key_delete(pthread_key_t);

為指定線程的特定數(shù)據(jù)鍵設置綁定的值

extern int pthread_setspecific(unsigned long, const void*);

獲取綁定的值

extern void *pthread_getspecific(unsigned long);

objc tls 實現(xiàn)

 typedef pthread_key_t tls_key_t;

static inline tls_key_t tls_create(void (*dtor)(void*)) { 
    tls_key_t k;
    pthread_key_create(&k, dtor); 
    return k;
}
static inline void *tls_get(tls_key_t k) { 
    return pthread_getspecific(k);
}
static inline void tls_set(tls_key_t k, void *value) { 
    pthread_setspecific(k, value); 
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末男摧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子译打,更是在濱河造成了極大的恐慌耗拓,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扶平,死亡現(xiàn)場離奇詭異帆离,居然都是意外死亡,警方通過查閱死者的電腦和手機结澄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岸夯,“玉大人麻献,你說我怎么就攤上這事〔掳纾” “怎么了勉吻?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旅赢。 經(jīng)常有香客問我齿桃,道長,這世上最難降的妖魔是什么煮盼? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任短纵,我火速辦了婚禮,結(jié)果婚禮上僵控,老公的妹妹穿的比我還像新娘香到。我一直安慰自己,他們只是感情好报破,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布悠就。 她就那樣靜靜地躺著,像睡著了一般充易。 火紅的嫁衣襯著肌膚如雪梗脾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天盹靴,我揣著相機與錄音炸茧,去河邊找鬼瑞妇。 笑死,一個胖子當著我的面吹牛宇立,可吹牛的內(nèi)容都是我干的踪宠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼妈嘹,長吁一口氣:“原來是場噩夢啊……” “哼柳琢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起润脸,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤柬脸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毙驯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倒堕,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年爆价,在試婚紗的時候發(fā)現(xiàn)自己被綠了垦巴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡铭段,死狀恐怖骤宣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情序愚,我是刑警寧澤憔披,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站爸吮,受9級特大地震影響芬膝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜形娇,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一锰霜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧埂软,春花似錦锈遥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至炫七,卻和暖如春爬立,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背万哪。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工侠驯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抡秆,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓吟策,卻偏偏與公主長得像儒士,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子檩坚,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容