python与人工智能应用锁_linux应用锁的搜索结果-阿里云开发者社区
Linux中的spinlock和mutex
Linux中的spinlock和mutex
作者
digoal
日期
2016-11-09
標簽
PostgreSQL , Linux , spin lock , mutex , 自旋鎖 , 搶占鎖
背景
最近在壓測PostgreSQL同步流復制時,遇到一個mutex鎖的瓶頸問題。
具體見?《PostgreSQL 同步流復制鎖瓶頸分析》
PG是以backend process睡眠,然后通過sender喚醒的方式來處理同步等待的問題。
轉(zhuǎn)一篇文章,了解一下spinlock, mutex。
http://www.aichengxu.com/view/2456962
spinlock (自旋鎖)
自旋鎖是專為防止多處理器并發(fā)而引入的一種鎖,它在內(nèi)核中大量應(yīng)用于中斷處理等部分(對于單處理器來說,防止中斷處理中的并發(fā)可簡單采用關(guān)閉中斷的方式,不需要自旋鎖)。
自旋鎖最多只能被一個內(nèi)核任務(wù)持有,如果一個內(nèi)核任務(wù)試圖請求一個已被爭用(已經(jīng)被持有)的自旋鎖,那么這個任務(wù)就會一直進行忙循環(huán)——旋轉(zhuǎn)——等待鎖重新可用。
要是鎖未被爭用,請求它的內(nèi)核任務(wù)便能立刻得到它并且繼續(xù)進行。自旋鎖可以在任何時刻防止多于一個的內(nèi)核任務(wù)同時進入臨界區(qū),因此這種鎖可有效地避免多處理器上并發(fā)運行的內(nèi)核任務(wù)競爭共享資源。
事實上,自旋鎖的初衷就是:
在短期間內(nèi)進行輕量級的鎖定。一個進程去獲取被爭用的自旋鎖時,請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應(yīng)該被持有時間過長(等待時CPU被獨占)。如果需要長時間鎖定的話, 最好使用信號量(睡眠,CPU資源可出讓)。
簡單的說,自旋鎖在內(nèi)核中主要用來防止多處理器中并發(fā)訪問臨界區(qū),防止內(nèi)核搶占造成的競爭。另外自旋鎖不允許任務(wù)睡眠(持有自旋鎖的任務(wù)睡眠會造成自死鎖——因為睡眠有可能造成持有鎖的內(nèi)核任務(wù)被重新調(diào)度,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。
死鎖:假設(shè)有一個或多個內(nèi)核任務(wù)和一個或多個資源,每個內(nèi)核都在等待其中的一個資源,但所有的資源都已經(jīng)被占用了。這便會發(fā)生所有內(nèi)核任務(wù)都在相互等待,但它們永遠不會釋放已經(jīng)占有的資源,于是任何內(nèi)核任務(wù)都無法獲得所需要的資源,無法繼續(xù)運行,這便意味著死鎖發(fā)生了。自死瑣是說自己占有了某個資源,然后自己又申請自己已占有的資源,顯然不可能再獲得該資源,因此就自縛手腳了。
spinlock特性:
防止多處理器并發(fā)訪問臨界區(qū),
1、非睡眠(該進程/LWP(Light Weight Process)始終處于Running的狀態(tài))
2、忙等 (cpu一直檢測鎖是否已經(jīng)被其他cpu釋放)
3、短期(低開銷)加鎖
4、適合中斷上下文鎖定
5、多cpu的機器才有意義(需要等待其他cpu釋放鎖)
信號量與互斥量
Linux中的信號量是一種睡眠鎖。如果有一個任務(wù)試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然后讓其睡眠。這時處理器獲得自由去執(zhí)行其它代碼。當持有信號量的進程將信號量釋放后,在等待隊列中的一個任務(wù)將被喚醒,從而便可以獲得這個信號量。
信號量的睡眠特性,使得信號量適用于鎖會被長時間持有的情況;只能在進程上下文中使用,因為中斷上下文中是不能被調(diào)度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
信號量基本使用形式為:
static DECLARE_MUTEX(mr_sem); //聲明互斥信號量
if(down_interruptible(&mr_sem))
//可被中斷的睡眠,當信號來到,睡眠的任務(wù)被喚醒
//臨界區(qū)
up(&mr_sem);
struct semaphore數(shù)據(jù)類型,down(struct semaphore * sem)和up(struct semaphore * sem)是占用和釋放
struct mutex數(shù)據(jù)類型,mutex_lock(struct mutex *lock)和mutex_unlock(struct mutex *lock)是加鎖和解鎖
競爭信號量與互斥量時需要進行進程睡眠和喚醒,代價較高,所以不適于短期代碼保護,適用于保護較長的臨界區(qū)
互斥量與信號量的區(qū)別
1. 互斥量用于線程的互斥,信號量用于線程的同步
這是互斥量和信號量的根本區(qū)別,也就是互斥和同步之間的區(qū)別
互斥:
是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的
同步:
是指在互斥的基礎(chǔ)上(大多數(shù)情況),通過其它機制實現(xiàn)訪問者對資源的有序訪問。在大多數(shù)情況下,同步已經(jīng)實現(xiàn)了互斥,特別是所有寫入資源的情況必定是互斥的。少數(shù)情況是指可以允許多個訪問者同時訪問資源
2. 互斥量值只能為0/1,信號量值可以為非負整數(shù)
也就是說,一個互斥量只能用于一個資源的互斥訪問,它不能實現(xiàn)多個資源的多線程互斥問題。信號量可以實現(xiàn)多個同類資源的多線程互斥和同步。當信號量為單值信號量是,也可以完成一個資源的互斥訪問
3. 互斥量的加鎖和解鎖必須由同一線程分別對應(yīng)使用,信號量可以由一個線程釋放,另一個線程得到
特性:
1、睡眠 (系統(tǒng)會將CPU切換給其他的進程/LWP運行。)
2、必須進程上下文(可調(diào)度)
3、長期加鎖
信號量和自旋鎖區(qū)別
雖然聽起來兩者之間的使用條件復雜,其實在實際使用中信號量和自旋鎖并不易混淆。注意以下原則:
如果代碼需要睡眠——這往往是發(fā)生在和用戶空間同步時——使用信號量是唯一的選擇。由于不受睡眠的限制,使用信號量通常來說更加簡單一些。
如果需要在自旋鎖和信號量中作選擇,應(yīng)該取決于鎖被持有的時間長短。理想情況是所有的鎖都應(yīng)該盡可能短的被持有,但是如果鎖的持有時間較長的話,使用信號量是更好的選擇。
另外,信號量不同于自旋鎖,它不會關(guān)閉內(nèi)核搶占,所以持有信號量的代碼可以被搶占。這意味者信號量不會對影響調(diào)度反應(yīng)時間帶來負面影響。
自旋鎖和信號量的選擇
需求
建議的加鎖方法
低開銷加鎖
優(yōu)先使用自旋鎖
短期鎖定
優(yōu)先使用自旋鎖
長期加鎖
優(yōu)先使用信號量
中斷上下文中加鎖
使用自旋鎖
持有鎖是需要睡眠、調(diào)度
使用信號量
以上有部分內(nèi)容轉(zhuǎn)自?http://www.linuxidc.com/Linux/2011-03/33741.htm
以下內(nèi)容轉(zhuǎn)自?http://blog.sina.com.cn/s/blog_0001988f0101f42l.html
spinlock mutex語義上是一樣的,都是對一臨界區(qū)加鎖保護,
區(qū)別是mutex得不到鎖會睡眠,因此不能在中斷上下文中使用。
另外,解鎖的一定是上鎖的那個 semaphore 得不到鎖會睡眠,也不能用在中斷中, 上鎖的不一定負責解鎖 。
rwlock 很好理解了,可多個讀,只有一個寫者,同樣會引起睡眠
最重要的就是只有spinlock 可以用在中斷上下文中.
至于wait_queue,不是同步手段,是內(nèi)核管理sleeping進程的一種手段
什么是等待隊列?
在軟件開發(fā)中任務(wù)經(jīng)常由于某種條件沒有得到滿足而不得不進入睡眠狀態(tài),然后等待條件得到滿足的時候再繼續(xù)運行,進入運行狀態(tài)。這種需求需要等待隊列機制的支持。
而且semaphore(我不知道所有的實現(xiàn)是不是這樣)中也用到了wait_queue_head
spinlock和信號量sem的區(qū)別
重點:死循環(huán)/睡眠
spinlock只是自旋鎖不會引起調(diào)用者睡眠,如果自旋鎖已經(jīng)被別的執(zhí)行單元保持,調(diào)用者就一直循環(huán)在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖。sem則會導致調(diào)用睡眠。然后應(yīng)用上就是前者可以在中斷處理中使用,后者不行。
信號量是針對使用時間比較長的共享資源,而自旋鎖的則一般時間較短.一般的申請鎖被其它保存則循環(huán)不止的等待.
Spinlock不斷的檢查等待的對象是否就緒,該進程/LWP始終處于Running的狀態(tài)
Sem使該進程/LWP進入Wait轉(zhuǎn)臺,系統(tǒng)會將CPU切換給其他的進程/LWP運行。
由于這個根本特性的不同,導致了以下用法上的不同:
1. Spinlock 只適用于短暫的等待,因為沒有進程切換所以對于短暫等待他的效率會比較高。但是對于長時間等待,由于它的CPU占用是100% 等的越長越不合算。
2. Spinlock只能在多個CPU的系統(tǒng)上用,因為等待者占據(jù)了100%的CPU,只由另外一個CPU上的進程才能解鎖。
兩者都是用于Linux內(nèi)核互斥。避免并發(fā),防止競爭,對系統(tǒng)公共資源或者共有數(shù)據(jù)進行合理保護的。SpinLock的出現(xiàn)是因為Symmetric Multi-Processor的出現(xiàn),如果是UniProcessor,用簡單的DisableIRQ就可以滿足其要求。Spin Lock是通過Poll方式的,其可以說是一個Test and Set or Test andClear的模型的延伸。而Semaphore則是傳統(tǒng)的IPC,是通過Sleep and Wake up方式實現(xiàn)的。通過SpinLock and Semaphore兩者的實現(xiàn)機制則,我們可以很明晰的看出兩者的應(yīng)用場合。
(在高并發(fā)的地方,輪詢比睡眠更高效)
Semaphore是一件可以容納N人的房間,如果人不滿就可以進去,如果人滿了,就要等待有人出來。對于N=1的情況,稱為binarysemaphore。一般的用法是,用于限制對于某一資源的同時訪問。
Binarysemaphore與Mutex的差異:
在有的系統(tǒng)中Binarysemaphore與Mutex是沒有差異的。在有的系統(tǒng)上,主要的差異是mutex一定要由獲得鎖的進程來釋放。而semaphore可以由其它進程釋放(這時的semaphore實際就是個原子的變量,大家可以加或減),因此semaphore可以用于進程間同步。Semaphore的同步功能是所有系統(tǒng)都支持的,而Mutex能否由其他進程釋放則未定,因此建議mutex只用于保護criticalsection。而semaphore則用于保護某變量,或者同步。
另一個概念是spin lock,這是一個內(nèi)核態(tài)概念。spinlock與semaphore的主要區(qū)別是spin lock是busywaiting,而semaphore是sleep。對于可以sleep的進程來說,busywaiting當然沒有意義。對于單CPU的系統(tǒng),busywaiting當然更沒意義(沒有CPU可以釋放鎖)。因此,只有多CPU的內(nèi)核態(tài)非進程空間,才會用到spin lock。Linuxkernel的spinlock在非SMP的情況下,只是關(guān)irq,沒有別的操作,用于確保該段程序的運行不會被打斷。其實也就是類似mutex的作用,串行化對critical
section的訪問。但是mutex不能保護中斷的打斷,也不能在中斷處理程序中被調(diào)用。而spinlock也一般沒有必要用于可以sleep的進程空間。
spinlock是多CPU下的同步機制,在獲取鎖時,如果失敗,它不會掛起當前的執(zhí)行過程。與之相對的,mutex和semaphore等同步機制,如果獲取mutex或semaphore失敗,它會掛起當前的執(zhí)行過程,而在mutex或semaphore退出是,喚醒相應(yīng)的過程。
不同的同步機制,是為了解決不同的問題。在單cpu上,不可能有spinlock,因為當前只能有一個活動的執(zhí)行路徑。而mutex或者semaphore則可以掛起當前的線程或者進程,CPU這時可以做其他的事情,等到掛在mutex或者semaphore上的進程被喚醒時,再繼續(xù)執(zhí)行被掛起的路徑。
可以想象,spinlock的設(shè)計并不是不能支持掛起當前執(zhí)行過程的操作。只是,在內(nèi)核中,掛起當前的執(zhí)行過程,就必須先能夠標識這個過程。內(nèi)核線程,或者進程,都有相應(yīng)的結(jié)構(gòu);但是,哪些不屬于這兩種的執(zhí)行過程,就必須使用spinlock。還有,如果一組進程在執(zhí)行過程中,要求必須是同步執(zhí)行,不能被打斷,這種情況下spinlock也是必須的。
說了這么多,主要的意思就是說,不能的同步機制適用于不同的場景,解決不同的問題。沒有一種同步機制可以解決所有的問題,這也是為什么linux里面不斷有新的同步機制被引入內(nèi)核。當新的問題出現(xiàn)時,現(xiàn)有的機制不能解決,或者不能很好解決這個問題時,就有必要引入新的機制來解決這個問題。
鎖是一種協(xié)議,是有共享臨界區(qū)的執(zhí)行過程之間達成的協(xié)議。有了api,并不能保證程序的正確,還需要正確的,合理的使用api。尤其是在多cpu情況下,鎖的使用,對性能有很大的影響。最好的辦法就是不使用鎖,每個CPU都是完全獨立的運行。這也要看具體的應(yīng)用,如果數(shù)據(jù)之間沒有關(guān)聯(lián),當然可以獨立地去處理;反之,則必須要鎖來保護。
比如用multicore實現(xiàn)網(wǎng)絡(luò)包的轉(zhuǎn)發(fā)時,當然可以把某個流綁定到某個CPU上,假設(shè)流與流直接是完全獨立的,這種情況下,每個CPU都可以獨立的處理屬于自己的流,不需要和其他CPU共享數(shù)據(jù)。但是,由于不同的流,流量是不同的,這樣,CPU的能力沒有被充分的利用,資源的使用也不平衡。這樣的設(shè)計并不能很好的解決問題。
選擇哪種設(shè)計方案,要綜合的去考慮,沒有最完美的解決方案,因為很多需求是相互沖突的,一個折衷的方案就是最后的選擇。
文章
關(guān)系型數(shù)據(jù)庫 · Linux · 調(diào)度 · PostgreSQL
2016-11-24
總結(jié)
以上是生活随笔為你收集整理的python与人工智能应用锁_linux应用锁的搜索结果-阿里云开发者社区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: virtual box一直正在加载文件_
- 下一篇: python程序发布 ubuntu_在u