設定程序綁定狀态的函數pthread_attr_setscope
pthread_attr_t 指向屬性結構的指針
第二個參數 綁定類型 pthread_scope_system()
pthread_scope_process(非綁定)
建立一個綁定線程
線程屬性結構
pthread_attr_t
#include <pthread.h>
pthread_attr_t attr;
pthread_t tid;//線程辨別符id
//初始化屬性值,均設為預設值
//代碼建立綁定線程
//初始化線程屬性,均設為預設值
pthread_attr_init(&attr);
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);設定線程綁定狀态函數
pthread_scope_system(綁定)
pthread_scope_process(非綁定的)
pthread_create(&tid,&attr,(void *)my_function,NULL);
線程是否綁定 決定影響線程的響應速度
線程分離狀态 決定一個線程以什麼樣的方式終止
線程分離狀态決定線程什麼方式終止自己
線程的預設屬性 非分離狀态
非分離狀态下,原有的線程等待建立的線程結束
pthread_join等待線程結束
原有的線程等待建立的線程結束,隻有當pthread_join()函數傳回 建立的
線程才算結束 才能釋放自己占用系統資源
分離線程不是這個樣子 沒有被其它的線程所等待 分離線程 沒有被其它線程等待
自己運作結束了 ,線程 就終止 了
馬上釋放系統資源
設定線程分離狀态函數pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);
第二個參數為pthread_attr_setdetachstate()
pthread_create_detached
pthread_create_joinable
如果設定一個線程為分離線程 而線程運作又非常快
很可能此線程在pthread_create函數傳回之前就終止了
終止以後就有可能将線程号和系統資源移交給其它的線程使用
這樣調用pthread_create的線程就得到了錯誤的線程号
避免這種情況采取一定的同步措施
在被建立的線程裡面調用pthread_cond_timewait
讓線程等待一會
留出足夠的時間讓函數pthread_create傳回
設定一段等待時間,是在多線程程式設計裡面常用的方法
不能使用wait() wait使整個程序睡眠,并不能解決線程同步問題
屬性 線程優先級priority 存在于結構 sched_param
pthread_attr_getschedparam
pthread_attr_setschedparam
一般來說我們總是先取優先級,對取得值進行修改後再存放回去
線程的屬性優先級sched_param
sched.h sched_param
sched_param sched.h
#include <sched.h>
pthread_t tid;
sched_param param;
int newprio = 20;
pthread_attr_init(&attr);//
pthread_attr_getschedparam(&attr,&param);
param.sched_priority = newprio;
pthread_attr_setschedparam(&attr,&param);
pthrea_create(&tid,&attr,(void *)myfunction,myarg);
線程的資料處理
和程序相比 線程的最大優點之一 資料共享性
各個線程共享程序處沿襲的資料段,可以友善的擷取,修改資料
線程的資料共享性在帶來友善性的同僚 也給多線程程式設計帶來了問題
我們必須當心有多個不同的程序通路相同的變量
線程資料處理
線程
函數中
線程中共享的變量必須用關鍵字volatile定義 防止編譯器在 gcc -OX
防止編譯器在優化時改變了使用方式
為了保護變量 我們必須使用信号量 signal metux 保證對變量正确使用
線程資料
單線程程式 兩種基本資料
global variable local variable;
多線程程式中 第三種資料類型
tsd thread-specific data
和全局變量象
線程内部 各個函數可以像使用全局變量一樣調用
為每個線程建立一個建 線程和建相關聯
在各個線程路面 都使用這個建來指代線程資料 在不同的線程裡
和線程資料相關的函數
建立建 為一個鍵指定線程資料
從一個鍵讀取線程資料 删除鍵
volatile 保護變量 使用信号量 互斥 保證我們對變量的正确使用
單線程程式裡面 兩種基本的資料 全局 變量 局部變量
多線程 有三種 資料類型
線程資料thread_specific da ta
線程資料和全局變量很像
線程内部 各個函數可以像使用全局變量一樣調用 對線程外部的其他線程 不可見 資料的必要性
errno
errno 線程變量
線程資料建立建 線程和建相關聯在各個線程裡都使用鍵指代線程資料
在不同的線程 鍵指代的資料不同 在同一個線程裡 代表同樣的資料
線程資料隻線上程内部;
實作線程資料變量 ,需要為每個線程建立鍵 線程再和建關聯
各個線程裡都使用鍵代指線程資料
線程資料相關函數
建立鍵 為一個鍵指定線程資料
從鍵讀取線程資料
删除鍵
建立鍵函數portable
extern init pthread_key_create __P((pthread_key_t *__key,void (* _destr_function)(void *)))
第一個參數指向一個鍵值指針
第二個參數
指明了destructor
destructor參數不為空
每當線程結束 系統将調用這個函數釋放綁定到鍵上的記憶體塊
pthread_once((pthread_once_t *once_control,void (*initroutine)(void)))
做到每個線程中資料都是鍵對應線程的資料 ,各個線程之間的線程資料 是對立的
互斥鎖
保證一段時間内隻有一個線程執行一段代碼
讀寫程式公用緩沖區
緩沖區隻儲存一條資訊 緩沖區隻有兩個狀态 有資訊沒資訊
void reader_function()
char buffer;
int buffer_has_item=0;
pthread_mutex_t mutex;
struct timespec delay
struct timespec delay;
void main(void)
{
pthread_t reader;
//定義延遲時間
delay.tv_sec = 2;
delay.tv_nec = 0;
}
使用預設屬性初始化互斥鎖對象
pthread_mutex_init(&mutex,NULL);
pthread_create(&reader,pthread_attr_default,);
條件變量
使用互斥鎖實作線程間資料共享和通信
互斥鎖明顯缺點 隻有兩種狀态
條件變量通過允許線程阻塞和等待另另一個線程發送信号方法彌補互斥鎖的不足
條件變量的結構為pthread_cond_t
condition;
pthread_cond_init()用來初始化一個條件變量
extern init pthread_cond_init __p((pthread_cond_t * __cond,__const pthread_cond arrt_t * _ cond attr));
第一個參數指向結構體指針
pthread_cond_t
cond_attr 指向結構體的指針
pthread_condattr_t是條件變量的屬性結構 和互斥鎖一樣我們可以用它來設定條件變量是
pthread_cond_destroy(pthread_cond_t cond)
釋放一個條件變量的函數
pthread_cond_wait()使線程阻塞在一個條件變量上
線程解開mutex指向的鎖并被條件變量cond阻塞
程序在記憶體中有3部分
資料段 堆棧段 代碼段
代碼段
存放程式代碼的資料,如果有數個程序運作同一個程式 那麼他們就可以使用同一個代碼段
數個程序同時運作同一個程式 可以同時使用同一個
堆棧段 存放的是子程式的傳回位址
參數以及程式的
參數 程式的局部變量 主要儲存程序的執行環境
這裡用到了堆棧 先進後出 具有記憶上一次執行環境
資料段:存放程式的全局變量常數;
動态資料配置設定的資料空間
系統如果同時運作數個相同的程式 他們之間就不能使用同一個堆棧和資料段
函數傳回值就是程序資料段所連接配接的實際位址,共享記憶體的位址
使用共享存儲實作程序間通信注意 對資料存儲的同步 必須確定一個程序去°資料 它所想要的資料已經寫好了
通信信号量被用來實作對共享存儲資料存儲的同步;
動态函數庫産生的可執行檔案比較小,動态函數庫在編譯的時候
并沒有被編譯進目标代碼
程式執行到相關函數時才調用該函數庫相應函數
動态函數所産生的可執行檔案比較小 由于函數 沒有被整合進你的程式 程式運作時動态申請并調用
是以程式是運作環境中必須提供相應的庫 動态函數庫的改變 不影響程式,動态函數庫的更新比較友善
O0
O
o00O
程式執行到相關函數才調用該函數裡的 相關函數 由于函數庫沒有被整合進你的程式 而是程式運作動态申請調用
程式運作環境提供相應的庫
oO0
互斥量
mutex
互斥量 用pthread_mutex_t資料類型表示
兩種方式初始化
指派為常量pthread_mutex_initializer互斥量動态配置設定
pthread_mutex_init
pthread_mutex_destroy;
int pthread_mutex_init(pthread_mutex_t * __mutex,__const pthread_mutexattr_t *__mutexattr);
int pthread_mutex_destroy(pthread_mutex_t *__mutex);
傳回值,成功0
加鎖pthread_mutex_lock
解鎖pthread_mutex_unlock;
int pthread_mutex_lock(pthread_mutex_t *__mutex);
int pthread_mutex_unlock(pthread_mutex_t *__mutex);
适用于度的次數大于寫的情況
int pthread_rwlock_init(pthread_rwlock_t *__restrict __rwlock,__const pthread_rwlockattr_t *__restrict __attr);
int pthread_rwlock_destroy(pthread_rwlock_t *__rwlock);
讀加鎖
int pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock);
寫加鎖
int pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock);
pthread_cond_t資料類型表示,條件變量本身由互斥量保護
condination variables mutex variables 保護 改變條件狀态前鎖住互斥量
條件變量初始化
指派常量pthread_cond_initializer;
條件量初始化 兩種方式
使用指派常量pthread_cond_initializer
使用pthread_cond_init函數
int pthread_cond_init(pthread_cond_t *__restrict_cond,__const pthread_condattr_t *__restrict __cond_mutex)
如果一個程序中某一個線程調用了一個阻塞的系統調用,該程序包括該程序中的其他線程同時被阻塞
使用者級線程缺點是在一個程序中的多個線程的排程中無法發揮多處理器的優勢
核心級
核心級别線程允許不同程序中的線程按照同一相對優先排程方法進行排程
線程允許不同程序中的線程安裝同一相對優先排程方法進行排程,發揮多核處理器并發優勢
既可以滿足多核處理器 也可以最大限度減少排程開銷
linux線程核外 核内提供的建立程序的接口do_fork();
核心提供了兩個系統調用clone fork
最終都用不同的參數調用do_fork核内API
核内提供的是建立程序的接口
實作線程 沒有核心對多程序共享資料段的支援不行 多程序 輕量級程序;
clone_vm共享記憶體空間
clone_fs 共享檔案系統資訊
clone_files共享檔案描述符表
clone_sighand共享信号句柄表clone_pid共享程序id,僅對核内程序0号程序有效;
使用fork系統調用 核心調用 do_fork()不适應任何共享屬性,程序擁有獨立的運作環境
使用pthread_create()建立線程 則最終設定了所有這些屬性來調用__clone()
參數又全部傳個do_fork(),進而建立的程序擁有共享的運作環境
隻有
linux線程在核内以輕量級程序的形式存在的,,擁有獨立的程序表項
所有建立 sync hronous delete 核外pthread 庫
pthRead庫使用管理線程__pthread_manager()管理線程 每個程序獨立且唯一
來管理線程的建立 為線程配置設定id 發送線程相關的信号cancal 主線程pthread_create調用則通過 管道将請求資訊傳個管理線程
綁定屬性:linux采用一對一線程機制 也就是一個使用者線程對應一個核心線程
綁定屬性就是指一個使用者線程固定地配置設定給一個核心線程
一個使用者線程固定地配置設定給一個核心線程
一對一線程機制 一個使用者線程對應一個核心線程
綁定屬性就是一個使用者線程固定地配置設定給一個核心線程,
cpu時間片段的排程是面向核心線程
而非綁定屬性指使用者線程和核心線程的關系不是始終固定的,
非綁定屬性指使用者線程和核心線程的關系不是始終固定的,而是由系統來控制配置設定的
分離屬性
分離屬性情況下 一個線程結束立即釋放它所占用的系統資源;
所占用的系統資源 沒有真正的終止
分離屬性用來決定一個線程以什麼樣的方式終止自己
需要注意的 一點
設定線程分離 線程運作非常快
它很可能在pthread_create線程建立函數傳回前就在終止了
終止以後就可能将線程号和系統資源移交給其他的線程使用,這時調用pthread_create
scope
pthread_scope_system
此線程與系統中所有線程競争
pthread_scope_proces 非綁定,此線程與程序中的其他線程競争
pthread_scope_system綁定,此線程與系統中所有的線程競争
int pthread_attr_getdetachstate(const pthread_attr_t *tattr,int *detachstate)
detachstate
int pthread_attr_setschedpolicy(pthread_attr_t *tattr,int policy)
int pthread_attr_getschedpolicy(pthread_attr_t *tattr,int *policy);
設定線程排程政策
policy
sched_fifo 先進先出
sched_rr 循環
sched_other 實作定義的方法
實則優先級
int pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param *param);
線程通路控制
互斥鎖mutex
通過鎖機制實作線程間同步synchronous
同時隻允許一個線程執行一個關鍵部分的代碼
隻允許一個線程執行一個關鍵部分的代碼
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_T *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
通路控制 access control;
互斥鎖 實作線程間的同步 同時隻允許 一個線程執行一個關鍵部分的代碼
初始化鎖
靜态指派
pthread_mutex_t mutex = pthread_mutex_initializer initializer;
lock trylock lock
加鎖 lock阻塞的等待鎖
trylock 立即傳回ebusy
解鎖unlock需要滿足加鎖狀态,
unlock需要滿足是加鎖狀态,同時由加鎖線程解鎖
deestroy 清除lock
此時鎖必須是unlock
recursive mutex
reentrant
mutex inter-thread同步工具同一線程 可以重複對
Concurrent
reentrantlock
crtical_section