線程互斥機(jī)制
Mutex變量就像一把“鎖”,是線程同步和保護(hù)共享數(shù)據(jù)的主要方式
Mutex可以用來阻止競爭
Pthreads中Mutex的基本概念
在任何時(shí)候,只有一個(gè)線程能夠獲得Mutex
盡管幾個(gè)線程想獲取一個(gè)Mutex,但是只有一個(gè)線程能夠成功
其他線程需要等待,直到獲取Mutex的線程放棄Mutex
線程必須輪流訪問需要保護(hù)的數(shù)據(jù)
線程經(jīng)常利用mutex來加鎖需要更新的全局變量,這也是幾個(gè)線程需要同時(shí)更新全局變量時(shí)使用的安全方法
這樣能保證在多線程環(huán)境下的全局變量的更新就如在單線程環(huán)境中一樣
此全局變量的更新屬于“臨界區(qū)”
創(chuàng)建和初始化mutex
使用mutex
各線程嘗試獲取mutex
但僅有一個(gè)線程能夠獲取mutex并擁有它
擁有mutex的線程執(zhí)行需訪問臨界資源的特定處理例程
擁有線程釋放mutex
其他線程闡述獲取mutex
重復(fù)上述步驟
銷毀 mutex
mutex變量創(chuàng)建/銷毀函數(shù)
pthread_mutex_init(mutex,attr) pthread_mutex_destroy(mutex) pthread_mutexattr_init(attr) pthread_mutexattr_destroy(attr)
互斥鎖創(chuàng)建
聲明mutex變量:pthread_mutex_t類型在使用前必須已經(jīng)初始化(兩種方式)靜態(tài)方式pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER動態(tài)方式int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)返回值成功返回0失敗返回錯(cuò)誤編號說明mutex初始時(shí)是unlocked(未加鎖的)的
普通鎖(PTHREAD_MUTEX_TIMED_NP)
默認(rèn)值,當(dāng)一個(gè)線程加鎖后,其余請求鎖的線程形成一個(gè)等待隊(duì)列,并在解鎖后按優(yōu)先級獲得鎖
嵌套鎖(PTHREAD_MUTEX_RECURSIVE_NP)
允許同一個(gè)線程對同一個(gè)鎖成功獲得多次,并通過多次unlock解鎖
如果是不同線程請求,則在加鎖線程解鎖時(shí)重新競爭
檢錯(cuò)鎖(PTHREAD_MUTEX_ERRORCHECK_NP)
如果同一個(gè)線程請求同一個(gè)鎖,則返回EDEADLK,否則與普通鎖動作相同
適應(yīng)鎖(PTHREAD_MUTEX_ADAPTIVE_NP)
動作最簡單的鎖類型,僅僅等待鎖解鎖后重新競爭
互斥鎖的屬性
用于設(shè)置mutex對象屬性如果使用它,那么它一定是 pthread_mutexattr_t 類型 (可以設(shè)置NULL作為缺省的)。pthreads標(biāo)準(zhǔn)定義三種可選的mutex屬性 protocol: 利用特定的協(xié)議來防止mutex優(yōu)先級倒置 prioceiling: 特定的mutex優(yōu)先級限制 process-shared: 特定進(jìn)程共享mutex 說明并不是所有的應(yīng)用提供所有這三種mutex屬性 屬性操作函數(shù)pthread_mutexattr_init():創(chuàng)建mutex屬性對象pthread_mutexattr_destroy():銷毀mutex屬性對象
函數(shù)原型int pthread_mutex_destroy(pthread_mutex_t *mutex)銷毀一個(gè)互斥鎖釋放它鎖占用的資源,且要求鎖當(dāng)前處于開放狀態(tài)
互斥鎖操作
加鎖int pthread_mutex_lock(pthread_mutex_t *mutex);若mutex已被其他線程加鎖,該調(diào)用會阻塞線程直到mutex被解鎖 嘗試加鎖int pthread_mutex_trylock(pthread_mutex_t *mutex);若mutex已經(jīng)被加鎖,該調(diào)用會立即返回一個(gè)“busy”錯(cuò)誤碼利用此調(diào)用可以防止在優(yōu)先級倒置所出現(xiàn)的死鎖 解鎖int pthread_mutex_unlock(pthread_mutex_t *mutex);當(dāng)擁有mutex的線程使用完保護(hù)資源后,應(yīng)該調(diào)用該解鎖mutex。在下面的情況中,將返回一個(gè)錯(cuò)誤 mutex已解鎖mutex被其他線程加鎖
條件變量
互斥鎖的缺點(diǎn)
通過控制存取數(shù)據(jù)來實(shí)現(xiàn)線程同步
線程需不斷輪詢條件是否滿足(忙等),消耗很多資源
條件變量
利用線程間共享的全局變量實(shí)現(xiàn)同步
條件變量使線程睡眠等待特定條件出現(xiàn)(無需輪詢)
使用方法
通常條件變量和互斥鎖同時(shí)使用
一個(gè)線程因等待“條件變量的條件成立”而掛起
另一個(gè)線程使”條件成立”(給出條件成立信號)
條件變量典型使用步驟
申明和初始化需要同步的全局?jǐn)?shù)據(jù)/變量(如count)
申明和初始化一個(gè)條件變量對象
申明和初始化對應(yīng)的mutex
創(chuàng)建若干進(jìn)程并運(yùn)行之
條件變量檢測
條件的檢測是在互斥鎖的保護(hù)下進(jìn)行的
如果條件為假,一個(gè)線程自動阻塞
如果另一個(gè)線程改變了條件,它發(fā)信號給關(guān)聯(lián)的條件變量,喚醒一個(gè)或多個(gè)等待它的線程,重新獲得互斥鎖,重新評價(jià)條件
pthread_cond_init (condition,attr) pthread_cond_destroy(condition) pthread_condattr_init(attr) pthread_condattr_destroy(attr)
條件變量的初始化
聲明條件變量:pthread_cond_t 類型使用前必須初始化,有兩種方法初始化方法靜態(tài)方式pthread_cond_t condition=PTHREAD_COND_INITIALIZER動態(tài)方式int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)被創(chuàng)建的條件變量ID通過 參數(shù)返回給調(diào)用線程該方法允許設(shè)置條件變量屬性
條件變量屬性
條件屬性僅僅定義一個(gè)屬性:process-shared 允條件變量可以被其他進(jìn)程中的線程訪問如果使用此條件變量屬性,必須把它定義為pthread_condattr_t 類型(缺省定義為NULL)說明并不是所有的實(shí)現(xiàn)都提供process-shared屬性屬性操作函數(shù)pthread_condattr_init():創(chuàng)建條件變量屬性對象 pthread_condattr_destroy():銷毀條件變量屬性對象
函數(shù)原型
int pthread_cond_destroy(pthread_cond_t *cond);
銷毀所指定的條件變量,同時(shí)將會釋放所給它分配的資源
調(diào)用該函數(shù)的線程并不要求等待在參數(shù)所指定的條件變量上
條件變量的等待
函數(shù)原型int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t mytex, const struct timespec *abstime);說明阻塞調(diào)用線程,直到滿足特定的條件當(dāng)該線程運(yùn)行時(shí),會被加鎖,阻塞時(shí)會自動解鎖當(dāng)收到信號喚醒線程時(shí),會被線程自動上鎖當(dāng)線程完成更新共享數(shù)據(jù)后,開發(fā)者有責(zé)任解鎖 這里的互斥鎖必須是普通鎖或者適應(yīng)鎖調(diào)用前必須由本線程加鎖,激活前要保持鎖是鎖定狀態(tài)
條件變量的激活
函數(shù)原型int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond);說明用于通知(喚醒)等待在條件變量上的另一線程在被加鎖后被調(diào)用,在完成pthread_cond_wait()運(yùn)行后必須解鎖 二者區(qū)別pthread_cond_signal()激活一個(gè)等待該條件的線程pthread_cond_broadcast()激活所有等待的線程如果多于一個(gè)線程處于阻塞狀態(tài),應(yīng)該用pthread_cond_broadcast()代替pthread_cond_signal()
條件變量等待與激活使用說明
如果在調(diào)用pthread_cond_wait()前先調(diào)用pthread_cond_signal(),將出現(xiàn)邏輯錯(cuò)誤 當(dāng)使用上述函數(shù)時(shí),必須正確的加鎖和解鎖在調(diào)用pthread_cond_wait()之前沒有成功加鎖mutex會導(dǎo)致線程不會阻塞 在調(diào)用 pthread_cond_signal()后沒有成功解鎖mutex,會導(dǎo)致pthread_cond_wait()一直運(yùn)行 (保持線程阻塞)
條件變量示例
inc_count(): thread 0, count = 1, unlocking mutexStarting watch_count(): thread 2inc_count(): thread 1, count = 2, unlocking mutexinc_count(): thread 0, count = 3, unlocking mutexinc_count(): thread 1, count = 4, unlocking mutexinc_count(): thread 0, count = 5, unlocking mutexinc_count(): thread 0, count = 6, unlocking mutexinc_count(): thread 1, count = 7, unlocking mutexinc_count(): thread 0, count = 8, unlocking mutexinc_count(): thread 1, count = 9, unlocking mutexinc_count(): thread 0, count = 10, unlocking mutexinc_count(): thread 1, count = 11, unlocking mutexinc_count(): thread 0, count = 12 Threshold reached.inc_count(): thread 0, count = 12, unlocking mutexwatch_count(): thread 2 Condition signal received.inc_count(): thread 1, count = 13, unlocking mutexinc_count(): thread 0, count = 14, unlocking mutexinc_count(): thread 1, count = 15, unlocking mutexinc_count(): thread 0, count = 16, unlocking mutexinc_count(): thread 1, count = 17, unlocking mutexinc_count(): thread 0, count = 18, unlocking mutexinc_count(): thread 1, count = 19, unlocking mutexinc_count(): thread 1, count = 20, unlocking mutexMain(): Waited on 3 threads. Done.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
生產(chǎn)者/消費(fèi)者問題
采用多線程技術(shù)解決生產(chǎn)者/消費(fèi)者問題
也稱有界緩沖區(qū)問題
多個(gè)生產(chǎn)者線程向緩沖區(qū)中寫數(shù)據(jù)
多個(gè)消費(fèi)者線程從緩沖區(qū)中讀取數(shù)據(jù)
生產(chǎn)者線程和消費(fèi)者線程必須滿足
生產(chǎn)者寫入緩沖區(qū)的數(shù)目不能超過緩沖區(qū)容量
消費(fèi)者讀取的數(shù)目不能超過生產(chǎn)者寫入的數(shù)目
緩沖區(qū)須被生產(chǎn)者/消費(fèi)者進(jìn)程互斥訪問生產(chǎn)者進(jìn)程多個(gè)并發(fā)寫進(jìn)程互斥改變寫指針寫入條件:緩沖區(qū)非滿消費(fèi)者進(jìn)程多個(gè)并發(fā)讀進(jìn)程互斥改變讀指針讀取條件:緩沖區(qū)非空讀/寫指針設(shè)計(jì)初始化時(shí),讀指針和寫指針均為0如果讀指針等于寫指針,則緩沖區(qū)為空如果(寫指針+ 1) % BUFFER_SIZE等于讀指針,則緩沖區(qū)為滿緩沖區(qū)結(jié)構(gòu)定義一個(gè)mutex變量:pthread_mutex_tlock兩個(gè)條件變量: pthread_cond_t 分別控制緩存空/滿狀態(tài)指示notemptynotfull
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
生產(chǎn)者/消費(fèi)者進(jìn)程
1、調(diào)用pthread_mutex_lock()對lock上鎖,并根據(jù)以下條件判斷緩沖區(qū)是否已滿;(writepos + 1) % BUFSIZE == readpos2、若滿,調(diào)用phtread_cond_wait()進(jìn)入阻塞,等待notfull條件變量;3、寫入數(shù)據(jù)并移動寫指針writepos;4、調(diào)用pthread_cond_signal()向消費(fèi)者信號通過notempty條件變量;5、調(diào)用pthread_mutex_unlock()對mutex解鎖。
1、調(diào)用pthread_mutex_lock()對lock上鎖,并根據(jù)以下條件判斷緩沖區(qū)是否為空;writepos == readpos2、若空,調(diào)用ptread_cond_wait()進(jìn)入阻塞,等待notempty條件變量;3、讀取數(shù)據(jù)并移動讀指針readpos;4、調(diào)用pthread_cond_signal()向消費(fèi)者信號通過notfull條件變量;5、調(diào)用pthread_mutex_unlock()對mutex解鎖。
生產(chǎn)者/消費(fèi)者問題—關(guān)鍵函數(shù)
線程管理相關(guān)函數(shù)int pthread_create( );int pthread_join();線程互斥控制相關(guān)函數(shù)int pthread_mutex_init();int pthread_mutex_lock();int pthread_mutex_unlock();線程條件變量控制相關(guān)函數(shù)int pthread_cond_init();int pthread_cond_wait();int pthread_cond_signal();
理發(fā)師問題
問題描述
一個(gè)理發(fā)店,只有一個(gè)理發(fā)師,只有n張可供顧客等待理發(fā)的椅子
理發(fā)師
如果沒有顧客,則理發(fā)師睡覺
否則開始理發(fā)
如果椅子為空,則繼續(xù)睡覺
顧客
如果進(jìn)入理發(fā)店發(fā)現(xiàn)理發(fā)師在睡覺,則把他叫醒
如果發(fā)現(xiàn)理發(fā)師在理發(fā),且有椅子為空,則坐下來等待
如果顧客發(fā)現(xiàn)椅子滿,則離開
出自:http://blog.csdn.net/wangzi11322/article/details/45765923