• <nav id="awwgi"><strong id="awwgi"></strong></nav>
  • <dd id="awwgi"></dd>
    • 027-87317566
    • 4352294@qq.com

    站多多網絡

    當前位置:首頁 > 網站建設
    新聞資訊

    力求視覺與交互的完美契合,以規范的流程和專注的態度,為您提供全方位的設計服務

    Go中的鎖源碼是如何實現Mutex的?

    來源:武漢網站建設  瀏覽量:  發布時間:2017-05-27 09:24:35

    準確地說是信號量(semaphore, mutext是semaphore的一種)的實現方式有兩種:wait的時候忙等待或者阻塞自己。

    忙等待和阻塞方式各有優劣:
    忙等待會使CPU空轉,好處是如果在當前時間片內鎖被其他進程釋放,當前進程直接就能拿到鎖而不需要CPU進行進程調度了。適用于鎖占用時間較短的情況,且不適合于單處理器。
    阻塞不會導致CPU空轉,但是進程切換也需要代價,比如上下文切換,CPU Cache Miss。
    下面看一下golang的源碼里面是怎么實現鎖的。golang里面的鎖有兩個特性:
    1.不支持嵌套鎖
    2.可以一個goroutine lock,另一個goroutine unlock

    這里要解釋一下atomic.CompareAndSwapInt32(),atomic包是由golang提供的low-level的原子操作封裝,主要用來解決進程同步為題,官方并不建議直接使用。我在上一篇文章中說過,操作系統級的鎖的實現方案是提供原子操作,然后基本上所有鎖相關都是通過這些原子操作來實現。CompareAndSwapInt32()就是int32型數字的compare-and-swap實現。cas(&addr, old, new)的意思是if *addr==old, *addr=new。大部分操作系統支持CAS,x86指令集上的CAS匯編指令是CMPXCHG。下面我們繼續看上面的lock函數。

    首先先忽略race.Enabled相關代碼,這個是go做race檢測時候用的,這個時候需要帶上-race,則race.Enabled被置為true。Lock函數的入口處先調用CAS嘗試去獲得鎖,如果m.state==0,則將其置為1,并返回。

    繼續往下看,首先將m.state的值保存到old變量中,new=old|mutexLocked。直接看能讓for退出的第三個if條件,首先調用CAS試圖將m.state設置成new的值。然后看一下if里面,如果m.state之前的值也就是old如果沒有被占用則表示當前goroutine拿到了鎖,則break。我們先看一下new的值的變化,第一個if條件里面new = old + 1<<mutexWaiterShift,結合上面的mutex的state各個位的意義,這句話的意思表示mutex的等待goroutine數目加1。還有awoke為true的情況下,要將m.state的標志位取消掉,也就是這句new &^= mutexWoken的作用。繼續看第三個if條件里面,如果里面的if判斷失敗,則走到runtime_Semacquire()。

    看一下這個函數runtime_Semacquire()函數,由于golang1.5之后把之前C語言實現的代碼都干掉了,所以現在很低層的代碼都是go來實現的。通過源碼中的定義我們可以知道這個其實就是信號量的wait操作:等待*s>0,然后減1。編譯器里使用的是sync_runtime.semacquire()函數。

    seg 1代碼片段semroot()返回結構體semaRoot。存儲方式是先對信號量的地址做移位,然后做哈希(對251取模,這個地方為什么是左移3位和對251取模不太明白)。semaRoot相當于和mutex.sema綁定??匆幌聅emaRoot的結構:一個sudog鏈表和一個nwait整型字段。nwait字段表示該信號量上等待的goroutine數目。head和tail表示鏈表的頭和尾巴,同時為了線程安全,需要使用一個互斥量來保護鏈表。這個時候細心的同學應該注意到一個問題,我們前面不是從Mutex跟過來的嗎,相當于Mutex的實現了使用了Mutex本身?實際上semaRoot里面的mutex只是內部使用的一個簡單版本,和sync.Mutex不是同一個?,F在把這些倒推回去,runtime_Semacquire()的作用其實就是semaphore的wait(&s):如果*s<0,則將當前goroutine塞入信號量s關聯的goroutine waiting list,并休眠。

    現在mutex.Lock()還剩下runtime_canSpin(iter)這一段,這個地方其實就是鎖的自旋版本。golang對于自旋鎖的取舍做了一些限制:1.多核; 2.GOMAXPROCS>1; 3.至少有一個運行的P并且local的P隊列為空。golang的自旋嘗試只會做幾次,并不會一直嘗試下去,感興趣的可以跟一下源碼。

    函數入口處的四行代碼和race detection相關,暫時不用管。接下來的四行代碼是判斷是否是嵌套鎖。new是m.state-1之后的值。我們重點看for循環內部的代碼。

    這兩句是說:如果阻塞在該鎖上的goroutine數目為0或者mutex處于lock或者喚醒狀態,則返回。

    這里先將阻塞在mutex上的goroutine數目減一,然后將mutex置于喚醒狀態。runtime_Semrelease和runtime_Semacquire的作用剛好相反,將阻塞在信號量上goroutine喚醒。有人可能會問喚醒的是哪個goroutine,那么我們可以看一下goroutine wait list的入隊列和出隊列代碼。

    如上所示,wait list入隊是插在隊尾,出隊是從頭出。
    武漢網站制作www.ceciliemathornetriathlete.com
    這篇文章太贊了我也要點贊!

    11

    鄭重聲明 Solemn Statement
    本文來源:http://www.ceciliemathornetriathlete.com 作者:武漢網站建設@武漢站多多 網絡營銷策劃,本文由武漢站多多版權所有,未經批準轉載必究。
    伊人精品久久久久中文字幕,黑人AV一区二区,富二代91在线国产精品手机观看,吴梦梦swag视频播放在线,99热欧美日韩精品视频在线观看,国产粉嫩主播自慰在线播放,少女萝莉无内衣无手遮无光圣,国产网红美女福利视频 日本的自我| 先锋影音中文字幕97| 泫雅广告中文字幕| 下面有根棒棒糖正在在线| 国产沙雕网剧李茂反转剧情| 爱到尽头国产情侣电影| 国产偷拍精品视频高清| 户外直播老年国产上传| 晚娘韩国| 麻豆传媒林予曦香蕉兄妹| 欧美种子后门| 日本 开户| 阳江女同性恋网| ig对fnc英文解说中文字幕| pr社最新福利视频在线观看| 久久99re8在线视频精品22| 午夜理论卡在线观看| 首之国产 医生护士搞| 国产古代伦理剧情| 国产情侣合集磁力+迅雷下载+迅雷下载+迅雷下载| 网红国产电风扇| 国产粉嫩主播自慰视频在线观看| 西出口 韩国| 麻豆传媒在线视频新春| 日本ippa| 美女萝莉cos战舰少女| 深田高清在线观看中文字幕| 萌白酱直播在线观看| 2018午夜宅男在线观看| 国产剧情新搬了的女邻居| 国产情侣普遍话对白| の国产直播| 韩国油压| 闺蜜头像欧美范儿两张| 琅琊榜在日本| 石家庄果冻传媒怎么了| 从中国寄东西到日本| 女同性恋相互甜穴| 国产 岛国 偷拍 自拍 迅雷下载| 国产 爽 主播| 韩国本地人| http://www.muyingshangcheng.com http://www.aloe-vera-hamburg.com http://www.pinkdiamondwedding.com http://www.xebabanhhoangtam.com http://www.687786.com http://www.cc989.com