wordpress模板怎么添加菜單百度seo排名優(yōu)化教程
一、互斥鎖
1、CPU 運(yùn)算過(guò)程
執(zhí)行完整個(gè)語(yǔ)句后,才會(huì)把數(shù)據(jù)寫(xiě)入內(nèi)存;如果執(zhí)行時(shí)被中斷,那么數(shù)據(jù)和上下文就會(huì)保存到線程的 TCB,但數(shù)據(jù)并不會(huì)被寫(xiě)入內(nèi)存。
1.1. 當(dāng) CPU 執(zhí)行完整個(gè)語(yǔ)句時(shí)

就用上圖舉個(gè)例子。?CPU 是如何執(zhí)行 a-- 這個(gè)句代碼的呢?
- 第一步,CPU 將內(nèi)存中變量 a 的值(100)拷貝到運(yùn)算器中。
- 第二步,在運(yùn)算器中減一。
- 第三步,把新的值(99)拷回變量 a 里。
1.2. 當(dāng) CPU 還未執(zhí)行完這個(gè)語(yǔ)句,線程就被換出時(shí)

以上圖為例,CPU 剛執(zhí)行完減 1 操作,線程就被換出。遇到這種沒(méi)執(zhí)行完語(yǔ)句的情況,CPU 會(huì)把計(jì)算數(shù)據(jù)和該線程執(zhí)行的上下文(即該線程執(zhí)行到哪一行代碼)拷到該線程的 TCB 里;然后再為下一個(gè)線程服務(wù)。
2、解決方案——互斥鎖(mutex)
2.0. 什么是互斥問(wèn)題
當(dāng)多個(gè)線程并發(fā)執(zhí)行,并訪問(wèn)同一個(gè)變量時(shí),就會(huì)很容易發(fā)生變量的一致性問(wèn)題。
如圖所示,假如我想讓變量?a 從 100 減到 0.
線程 1 在做完 a-- 操作后就被換出了:
?

線程 2 正常執(zhí)行完整個(gè)減 1 操作,并重復(fù)了很多次,直到減到 10,被換出,線程 1 進(jìn)來(lái)了:


而此時(shí) a 這個(gè)全局變量又從 10 變成 100 了。
所以,這個(gè)變量從始至終都只能被一個(gè)執(zhí)行流(線程)訪問(wèn)。
2.1. 互斥鎖原理
下面這是線程申請(qǐng)鎖和釋放鎖的匯編代碼:
lock: // 申請(qǐng)鎖movb $0, %alxchgb %al, mutexif (al 寄存器的內(nèi)容 > 0) return 0; // 申請(qǐng)鎖成功else 掛起等待;goto lock;unlock: // 釋放鎖movb $1, mutex喚醒等待 Mutex 的線程;return 0;

但是,如果當(dāng)該線程執(zhí)行完第一句后就被換出了,那么該線程會(huì)把 al 寄存器的值和上下文保存到 TCB;然后再被換出;然后第二個(gè)線程再進(jìn)來(lái)從上次的上下文開(kāi)始接著執(zhí)行。所以,其實(shí)申請(qǐng)鎖的本質(zhì)就是看哪個(gè)線程拿到 1,拿到 1 的那個(gè)線程就申請(qǐng)到鎖了。
2.2. 相關(guān)函數(shù)
2.2.1. pthread_mutex_t 類(lèi)型
就是互斥鎖的類(lèi)型。
2.2.2. pthread_mutex_lock 函數(shù)
這個(gè)函數(shù)用于申請(qǐng)互斥鎖。注意,這里只是把鎖加上而已,并不會(huì)創(chuàng)建鎖。?
2.2.3. pthread_mutex_unlock 函數(shù)
這個(gè)函數(shù)用于釋放鎖。注意,這里只是把鎖解開(kāi)了,鎖還在。
2.2.4. 初始化全局的鎖
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
2.2.5. 初始化局部變量的鎖?
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);參數(shù):
mutex:要初始化的互斥鎖
attr:nullptr
?2.2.6. 銷(xiāo)毀互斥鎖
int pthread_mutex_destroy(pthread_mutex_t *mutex);
這個(gè)函數(shù)是直接讓鎖消失。
注意:
- 如果創(chuàng)建的鎖是用宏創(chuàng)建的,就不能掉這個(gè)函數(shù)。?
- 一定要在解開(kāi)鎖了之后才能調(diào)用這個(gè)函數(shù)。
- 確保后面沒(méi)有線程用到這個(gè)鎖。
2.3. 臨界區(qū)
處于?pthread_mutex_lock 函數(shù)和?pthread_mutex_unlock 函數(shù)之間的區(qū)域就是臨界區(qū)。
2.4. 臨界資源
多線程執(zhí)行流共享的資源就叫做臨界資源。不過(guò),臨界資源都是每次只能讓一個(gè)一個(gè)線程訪問(wèn)的。但是當(dāng)線程申請(qǐng)鎖時(shí),那么鎖也是共享資源;所以申請(qǐng)鎖和釋放鎖本來(lái)就被匯編語(yǔ)言設(shè)計(jì)成原子性的(即只用一句匯編實(shí)現(xiàn))。
二、死鎖
1、產(chǎn)生死鎖的必要條件
- 互斥條件:一個(gè)資源每次只能被一個(gè)執(zhí)行流使用。
- 請(qǐng)求和保持條件:一個(gè)執(zhí)行流因請(qǐng)求資源而阻塞時(shí),它同時(shí)也持有已有的資源,且不釋放。
- 不剝奪條件:如果申請(qǐng)不到資源,只能等待,不能強(qiáng)行搶占。
- 循環(huán)條件:執(zhí)行流之間形成有環(huán)的等待資源的關(guān)系。
2、如何解決
- 破壞上面的 4 條必要條件的其中一條。
- 資源一次性分配。
- 加鎖順序一致。
- 避免未釋放的場(chǎng)景。
三、同步問(wèn)題
1、什么是同步
同步就是讓線程按照一定順序獲取資源,而不是一窩蜂地去搶。舉個(gè)例子,假如廁所是一個(gè)共享資源,一次只能一個(gè)人用。當(dāng)有人進(jìn)去后,就會(huì)有很多人在外面等。如果不同步的話,一旦廁所里的那個(gè)人出來(lái),全部人就會(huì)一窩蜂地去搶廁所;而如果剛出來(lái)的那個(gè)人的搶占能力非常強(qiáng),那么廁所就會(huì)一直被搶占能力最強(qiáng)的那個(gè)人占用,因?yàn)檫@個(gè)人可以出來(lái)后再搶。于是就會(huì)導(dǎo)致其他人長(zhǎng)時(shí)間沒(méi)得上廁所,進(jìn)而引發(fā)其他人的饑餓問(wèn)題。
因此,解決方法就是讓所有人排隊(duì),一個(gè)個(gè)上廁所。從廁所出來(lái)的人無(wú)論搶占能力強(qiáng)還是弱,都要去隊(duì)尾排隊(duì)。這種讓人們有序地使用廁所就是同步。而把線程看成人,那就就是線程的同步了。所以,總結(jié)來(lái)說(shuō),在保證數(shù)據(jù)安全的前提下,讓線程能夠按照某種特定的順序訪問(wèn)臨界資源,從而有效避免饑餓問(wèn)題,叫做同步。
2、條件變量
2.1. 什么是條件變量
還記得前面廁所排隊(duì)的例子嗎?條件變量就是這個(gè)等待隊(duì)列的頭節(jié)點(diǎn),當(dāng)申請(qǐng)到資源時(shí),線程就會(huì)從等待隊(duì)列出來(lái),然后訪問(wèn)共享資源;而如果線程沒(méi)申請(qǐng)到資源時(shí),該線程就會(huì)進(jìn)入以條件變量為頭節(jié)點(diǎn)的等待隊(duì)列里。
2.2. 相關(guān)函數(shù)
2.2.0.?pthread_cond_t 類(lèi)型
該類(lèi)型為條件變量類(lèi)型。
2.2.1.?初始化全局的條件變量
pthread_cond_t global_cond = PTHREAD_COND_INITIALIZER;
2.2.1. 初始化局部變量的條件變量
參數(shù)介紹
- cond:條件變量的地址。
- attr:?條件變量的性質(zhì)。
這個(gè)函數(shù)用于初始化條件變量。其實(shí)就是初始化等待隊(duì)列的頭節(jié)點(diǎn)。
2.2.2. pthread_cond_destroy 函數(shù)
參數(shù)介紹
- cond:傳條件變量的地址。?
注意:
- 如果創(chuàng)建的條件變量是用宏創(chuàng)建的,就不能掉這個(gè)函數(shù)。?
這個(gè)函數(shù)用于釋放條件變量。其實(shí)就是初始化等待隊(duì)列的頭節(jié)點(diǎn)。
2.2.3.?pthread_cond_wait 函數(shù)
參數(shù)介紹
cond:傳條件變量的地址。
mutex:傳互斥鎖的地址。?
此函數(shù)用于把線程加入等待隊(duì)列。如果此時(shí)沒(méi)申請(qǐng)到共享資源,該線程就會(huì)進(jìn)入以條件變量為頭節(jié)點(diǎn)的等待隊(duì)列里。
2.2.4.?pthread_cond_signal 函數(shù)
參數(shù)介紹
- cond:條件變量地址。?
此函數(shù)用于喚醒線程。 即當(dāng)線程申請(qǐng)到共享資源時(shí),這個(gè)函數(shù)就能讓一個(gè)線程的 TCB 退出以條件變量為頭節(jié)點(diǎn)的等待隊(duì)列。
2.2.5.?pthread_cond_broadcast 函數(shù)
參數(shù)介紹
- cond:條件變量地址。?
即當(dāng)線程申請(qǐng)到共享資源時(shí),這個(gè)函數(shù)就能讓所有線程的 TCB 退出以條件變量為頭節(jié)點(diǎn)的等待隊(duì)列。?
四、應(yīng)用:生產(chǎn)者消費(fèi)者問(wèn)題(cp 問(wèn)題)
1、什么是生產(chǎn)者消費(fèi)者問(wèn)題
簡(jiǎn)單來(lái)說(shuō),前提就是生產(chǎn)者和消費(fèi)者之間有一個(gè)共享資源(共享內(nèi)存),生產(chǎn)者負(fù)責(zé)向共享內(nèi)存放數(shù)據(jù),消費(fèi)者負(fù)責(zé)從共享內(nèi)存里拿數(shù)據(jù)。然后我們通過(guò)一定的策略解決它們的互斥與同步問(wèn)題。
2、3 種關(guān)系
2.1. 生產(chǎn)者與生產(chǎn)者
生產(chǎn)者與生產(chǎn)者之間是競(jìng)爭(zhēng)關(guān)系,因此生產(chǎn)者與生產(chǎn)者之間是互斥關(guān)系。
2.2. 生產(chǎn)者與消費(fèi)者
2.2.1. 互斥關(guān)系
因?yàn)橐WC公共資源的安全性,因此要讓生產(chǎn)者與消費(fèi)者處于互斥關(guān)系,每次只能有一個(gè)線程訪問(wèn)共享資源。
2.2.2. 同步關(guān)系
因?yàn)楣蚕韮?nèi)存里先有數(shù)據(jù),消費(fèi)者才可以拿數(shù)據(jù)。而生產(chǎn)者是負(fù)責(zé)向內(nèi)存放數(shù)據(jù)的。因此先有生產(chǎn)者向共享內(nèi)存放數(shù)據(jù),才有消費(fèi)者從共享內(nèi)存拿數(shù)據(jù),這是一種順序訪問(wèn)共享內(nèi)存;因此生產(chǎn)者與消費(fèi)者也處于同步關(guān)系。
2.3. 消費(fèi)者與消費(fèi)者
消費(fèi)者與消費(fèi)者之間是競(jìng)爭(zhēng)關(guān)系,因此生產(chǎn)者與生產(chǎn)者之間是互斥關(guān)系。