建設(shè)網(wǎng)站 教學(xué)反思seo網(wǎng)站優(yōu)化收藏
目錄
- 1. POSIX信號(hào)量
- 1.1 概念
- 2. 基于環(huán)形隊(duì)列的生產(chǎn)消費(fèi)者模型
- 2.1 環(huán)形隊(duì)列的基本原理
- 2.2 基本實(shí)現(xiàn)思想
- 3. 多生產(chǎn)多消費(fèi)
1. POSIX信號(hào)量
1.1 概念
信號(hào)量本質(zhì)是一個(gè)計(jì)數(shù)器,申請(qǐng)了信號(hào)量以后,可以達(dá)到預(yù)定臨界資源的效果。
POSIX信號(hào)量和SystemV信號(hào)量相同,都可以用于同步操作,達(dá)到無沖突訪問共享資源的目的。但POSIX可以用于線程間同步。
在未加鎖情況下,如果多個(gè)線程同時(shí)對(duì)臨界資源進(jìn)行訪問操作,是極度不安全的,所以想要實(shí)現(xiàn)多個(gè)線程并發(fā),需要有信號(hào)量的申請(qǐng)。
每個(gè)線程申請(qǐng)了信號(hào)量以后,相當(dāng)于對(duì)一塊臨界資源進(jìn)行了預(yù)定,并且將其分成一個(gè)個(gè)小資源,每個(gè)線程同時(shí)訪問該臨界資源不同區(qū)域,達(dá)到多線程并發(fā)的效果。
對(duì)于每個(gè)線程來說,想訪問臨界資源。都必須先申請(qǐng)信號(hào)量資源,這就涉及到了信號(hào)量的數(shù)目多少。
- P、V操作
這個(gè)過程其實(shí)就是對(duì)信號(hào)量進(jìn)行加加減減。申請(qǐng)信號(hào)量的過程有成功或者失敗,成功就是count–,失敗就是掛起等待,即P操作;釋放信號(hào)量就是count++,即V操作。
- PV操作的原子性實(shí)現(xiàn)
PV操作的原子性其實(shí)是對(duì)于其他PV操作而言的,即一個(gè)P或V操作不能被其他的PV操作給打斷,即需要實(shí)現(xiàn)PV操作的互斥。那么我們可以把PV操作的代碼當(dāng)成臨界區(qū),保證只有一個(gè)進(jìn)程能訪問臨界區(qū)即可。實(shí)現(xiàn)對(duì)臨界區(qū)資源的互斥訪問的方法有很多種,比如Peterson算法,禁用中斷,加鎖等等等
- 信號(hào)量的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):簡單,表達(dá)能力強(qiáng),用PV操作可以解決多種類型的同步/互斥問題
缺點(diǎn):不夠安全,PV操作使用不當(dāng)容易產(chǎn)生死鎖,遇到復(fù)雜同步互斥問題實(shí)現(xiàn)復(fù)雜
- 初始化信號(hào)量:
參數(shù):
pshared:0表示線程間共享,非零表示進(jìn)程間共享
value:期望申請(qǐng)的信號(hào)量初始值
- 銷毀信號(hào)量:
- 等待信號(hào)量:
功能:等待信號(hào)量,會(huì)將信號(hào)量的值減1
這其實(shí)是申請(qǐng)信號(hào)量的函數(shù):
是經(jīng)典的P操作,在申請(qǐng)信號(hào)量的過程中有重要作用。
- 發(fā)布信號(hào)量:
功能:發(fā)布信號(hào)量,表示資源使用完畢,可以歸還資源了,將信號(hào)量值加1
這個(gè)便是V操作,和V操作形成對(duì)比。
2. 基于環(huán)形隊(duì)列的生產(chǎn)消費(fèi)者模型
2.1 環(huán)形隊(duì)列的基本原理
多線程的情況下,實(shí)現(xiàn)一個(gè)基于環(huán)形隊(duì)列的生產(chǎn)消費(fèi)模型,來進(jìn)行環(huán)形隊(duì)列的并發(fā)訪問。
- 生產(chǎn)者和消費(fèi)者開始的時(shí)候,指向的就是同一個(gè)位置;在隊(duì)列為滿的時(shí)候,也指向同一個(gè)位置。
- 隊(duì)列為空的時(shí)候,應(yīng)該讓生產(chǎn)者先訪問;隊(duì)列為滿的時(shí)候,應(yīng)該讓消費(fèi)者先訪問。
所以,當(dāng)隊(duì)列既不為空又不為滿的時(shí)候,生產(chǎn)者和消費(fèi)者一定指向的不是同一個(gè)位置。
那么我們就可以利用這個(gè)原理,在生產(chǎn)者和消費(fèi)者不處于同一位置,那么久說明多個(gè)執(zhí)行流訪問的是臨界資源的不同區(qū)域,就可以實(shí)現(xiàn)并發(fā)。 但是這個(gè)工作是程序員本身完成的,而不是信號(hào)量設(shè)置好的。
2.2 基本實(shí)現(xiàn)思想
對(duì)于生產(chǎn)者來說,最關(guān)心的資源應(yīng)該是環(huán)形隊(duì)列中空的位置;對(duì)于消費(fèi)者來說,最關(guān)心的資源應(yīng)該是環(huán)形隊(duì)列中有數(shù)據(jù)的位置,其實(shí)就是資源存在的位置。
在這個(gè)模型中,要遵守幾個(gè)規(guī)則:
-
生產(chǎn)者不能把消費(fèi)者套一個(gè)圈,也就是說最多生產(chǎn)一圈,消費(fèi)者就要行動(dòng)了。
-
消費(fèi)者不能超過生產(chǎn)者
-
當(dāng)指向同一個(gè)位置的時(shí)候,要根據(jù)空、滿的狀態(tài)來判定誰先執(zhí)行
-
除此之外,生產(chǎn)和消費(fèi)可以并發(fā)執(zhí)行
對(duì)于生產(chǎn)者來說,我們申請(qǐng)格子資源,格子資源變少了,其實(shí)就是對(duì)格子資源做P操作,那么可以放的數(shù)據(jù)資源更多了,那此時(shí)也就相當(dāng)于對(duì)數(shù)據(jù)資源做V操作;消費(fèi)者同理。
所以可以通過釋放對(duì)方資源的方式來達(dá)到數(shù)據(jù)交互的效果。
3. 多生產(chǎn)多消費(fèi)
如果想實(shí)現(xiàn)多生產(chǎn)者和多消費(fèi)者同時(shí)工作,是必須要加鎖的,而這個(gè)加鎖的地方,是放在P操作之后。
生產(chǎn)者函數(shù)如下(消費(fèi)者函數(shù)同理):
void PutData(const int &data)
{sem_wait(&space_sem); // Ppthread_mutex_lock(&_mtx_);//加鎖q[consume_step] = data;consume_step++;consume_step %= cap;pthread_mutex_unlock(&_mtx_);//解鎖sem_post(&data_sem); //V
}
舉個(gè)例子:如果想要實(shí)現(xiàn)并發(fā),如果將鎖放在了P操作之前,就會(huì)造成PV操作之前都必須要申請(qǐng)到鎖的情況,這其實(shí)和單線程沒有區(qū)別,并且申請(qǐng)到了鎖以后,PV操作如果不成功,還是需要從新來申請(qǐng)鎖,所以效率也會(huì)更慢。
而放在P操作之后,可以理解為在申請(qǐng)鎖之前,多個(gè)線程就已經(jīng)申請(qǐng)到了信號(hào)量,即PV操作是成功的。那么此時(shí)只需要等待競爭鎖就行了。
而這里正是多生產(chǎn)多消費(fèi)的優(yōu)勢(shì),每次都只能一個(gè)線程生產(chǎn),一個(gè)線程消費(fèi),可以并發(fā)地獲取和處理任務(wù)。