欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何理解Go運(yùn)行時(shí)中的Mutex

這篇文章主要講解了“如何理解Go運(yùn)行時(shí)中的Mutex”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何理解Go運(yùn)行時(shí)中的Mutex”吧!

創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、網(wǎng)站制作、靜安網(wǎng)絡(luò)推廣、微信平臺(tái)小程序開發(fā)、靜安網(wǎng)絡(luò)營(yíng)銷、靜安企業(yè)策劃、靜安品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供靜安建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:chinadenli.net

sync.Mutex是一個(gè)high  level的同步原語,是為廣大的Go開發(fā)者開發(fā)應(yīng)用程序提供的一種數(shù)據(jù)結(jié)構(gòu),現(xiàn)在它的內(nèi)部實(shí)現(xiàn)邏輯比較復(fù)雜了,包含spin和饑餓處理等邏輯,它底層使用了運(yùn)行時(shí)的low  level的一些函數(shù)和atomic的一些方法。

而運(yùn)行時(shí)中的mutex是為運(yùn)行時(shí)內(nèi)部使用互斥鎖而提供的一個(gè)同步原語,它提供了spin和等待隊(duì)列,并沒有去解決饑餓狀態(tài),而且它的實(shí)現(xiàn)和sync.Mutex的實(shí)現(xiàn)也是不一樣的。它并沒有以方法的方式提供Lock/Unlock,而是提供lock/unlock函數(shù)實(shí)現(xiàn)請(qǐng)求鎖和釋放鎖。

Dan Scales 今年年初的時(shí)候又為運(yùn)行時(shí)的鎖增加了static locking rank的功能。他為運(yùn)行時(shí)的架構(gòu)無關(guān)的鎖(  architecture-independent  locks)定義了rank,并且又定義了一些運(yùn)行時(shí)的鎖的偏序(此鎖之前允許持有哪些鎖)。這是運(yùn)行時(shí)鎖的一個(gè)巨大改變,但是很遺憾并沒有一篇設(shè)計(jì)文檔詳細(xì)去描述這個(gè)功能的設(shè)計(jì),你可以通過提交的comment(#0a820007)和代碼中的注釋去了解runtime內(nèi)部鎖的代碼變化。

本質(zhì)上來說,這個(gè)功能用來檢查鎖的順序是不是按照文檔設(shè)計(jì)的順序執(zhí)行的,如果有違反設(shè)定的順序,就有可能死鎖發(fā)生。因?yàn)槿狈?zhǔn)確的文檔說明,并且這個(gè)功能主要是用來檢查運(yùn)行時(shí)鎖的執(zhí)行順序的,所以在本文中我把這一段邏輯抹去不介紹了。實(shí)際Go運(yùn)行時(shí)要開始這個(gè)檢查的話,你需要設(shè)置變量GOEXPERIMENT=staticlockranking。

那么接下來我們看看運(yùn)行時(shí)的mutex的數(shù)據(jù)結(jié)構(gòu)的定義以及l(fā)ock/unlock的實(shí)現(xiàn)。

運(yùn)行時(shí)mutex數(shù)據(jù)結(jié)構(gòu)

運(yùn)行時(shí)的mutex數(shù)據(jù)結(jié)構(gòu)很簡(jiǎn)單,如下所示,定義在runtime2.go中:

type mutex struct {     lockRankStruct     // Futex-based impl treats it as uint32 key,     // while sema-based impl as M* waitm.     // Used to be a union, but unions break precise GC.     key uintptr }

如果不啟用lock ranking,其實(shí)lockRankStruct就是一個(gè)空結(jié)構(gòu):

type lockRankStruct struct { }

那么對(duì)于運(yùn)行時(shí)的mutex,最重要的就是key字段了。這個(gè)字段針對(duì)不同的架構(gòu)有不同的含義。

對(duì)于dragonfly、freebsd、linux架構(gòu),mutex會(huì)使用基于Futex的實(shí)現(xiàn), key就是一個(gè)uint32的值。  Linux提供的Futex(Fast user-space mutexes)用來構(gòu)建用戶空間的鎖和信號(hào)量。Go  運(yùn)行時(shí)封裝了兩個(gè)方法,用來sleep和喚醒當(dāng)前線程:

  • futexsleep(addr uint32, val uint32, ns int64):原子操作`if addr == val { sleep  }`。

  • futexwakeup(addr *uint32, cnt uint32):?jiǎn)拘训刂穉ddr上的線程最多cnt次。

對(duì)于其他的架構(gòu),比如aix、darwin、netbsd、openbsd、plan9、solaris、windows,mutex會(huì)使用基于sema的實(shí)現(xiàn),key就是M*  waitm。Go 運(yùn)行時(shí)封裝了三個(gè)方法,用來創(chuàng)建信號(hào)量和sleep/wakeup:

  • func semacreate(mp *m):創(chuàng)建信號(hào)量

  • func semasleep(ns int64) int32: 請(qǐng)求信號(hào)量,請(qǐng)求不到會(huì)休眠一段時(shí)間

  • func semawakeup(mp *m):?jiǎn)拘裮p

基于這兩種實(shí)現(xiàn),分別有不同的lock和unlock方法的實(shí)現(xiàn),主要邏輯都是類似的,所以接下來我們只看基于Futex的lock/unlock。

請(qǐng)求鎖lock

如果不使用lock ranking特性,lock的邏輯主要是由lock2實(shí)現(xiàn)的。

func lock(l *mutex) {     lockWithRank(l, getLockRank(l)) } func lockWithRank(l *mutex, rank lockRank) {     lock2(l) } func lock2(l *mutex) {     // 得到g對(duì)象     gp := getg()     // g綁定的m對(duì)象的lock計(jì)數(shù)加1     if gp.m.locks < 0 {         throw("runtime&middot;lock: lock count")     }     gp.m.locks++     // 如果有幸運(yùn)光環(huán),原來鎖沒有被持有,一把就獲取到了鎖,就快速返回了     v := atomic.Xchg(key32(&l.key), mutex_locked)     if v == mutex_unlocked {         return     }     // 否則原來的可能是MUTEX_LOCKED或者M(jìn)UTEX_SLEEPING     wait := v     // 單核不進(jìn)行spin,多核CPU情況下會(huì)嘗試spin     spin := 0     if ncpu > 1 {         spin = active_spin     }          for {         // 嘗試spin,如果鎖已經(jīng)釋放,嘗試搶鎖         for i := 0; i < spin; i++ {             for l.key == mutex_unlocked {                 if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {                     return                 }             }             // PAUSE             procyield(active_spin_cnt)         }         // 再嘗試搶鎖, rescheduling.         for i := 0; i < passive_spin; i++ {             for l.key == mutex_unlocked {                 if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {                     return                 }             }             osyield()         }         // 再嘗試搶鎖,并把key設(shè)置為mutex_sleeping,如果搶鎖成功,返回         v = atomic.Xchg(key32(&l.key), mutex_sleeping)         if v == mutex_unlocked {             return         }                  // 否則sleep等待         wait = mutex_sleeping         futexsleep(key32(&l.key), mutex_sleeping, -1)     } }

unlock

如果不使用lock ranking特性,unlock的邏輯主要是由unlock2實(shí)現(xiàn)的。

func unlock(l *mutex) {     unlockWithRank(l) } func unlockWithRank(l *mutex) {     unlock2(l) } func unlock2(l *mutex) {     // 將key的值設(shè)置為mutex_unlocked     v := atomic.Xchg(key32(&l.key), mutex_unlocked)     if v == mutex_unlocked {         throw("unlock of unlocked lock")     }     // 如果原來有線程在sleep,喚醒它     if v == mutex_sleeping {         futexwakeup(key32(&l.key), 1)     }     //得到當(dāng)前的goroutine以及和它關(guān)聯(lián)的m,將鎖的計(jì)數(shù)減1     gp := getg()     gp.m.locks--     if gp.m.locks < 0 {         throw("runtime&middot;unlock: lock count")     }     if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack         gp.stackguard0 = stackPreempt     } }

總體來說,運(yùn)行時(shí)的mutex邏輯還不太復(fù)雜,主要是需要處理不同的架構(gòu)的實(shí)現(xiàn),它休眠喚醒的對(duì)象是m,而sync.Mutex休眠喚醒的對(duì)象是g。

感謝各位的閱讀,以上就是“如何理解Go運(yùn)行時(shí)中的Mutex”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)如何理解Go運(yùn)行時(shí)中的Mutex這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

網(wǎng)頁標(biāo)題:如何理解Go運(yùn)行時(shí)中的Mutex
新聞來源:http://chinadenli.net/article34/pehppe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化、用戶體驗(yàn)軟件開發(fā)、做網(wǎng)站、網(wǎng)站排名

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司