<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          字節(jié)跳動Go 語言面試會問哪些問題?

          共 975字,需瀏覽 2分鐘

           ·

          2022-03-15 22:39

          1、Mutex 幾種狀態(tài)


          • mutexLocked?— 表示互斥鎖的鎖定狀態(tài);

          • mutexWoken?— 表示從正常模式被從喚醒;

          • mutexStarving?— 當前的互斥鎖進入饑餓狀態(tài);

          • waitersCount?— 當前互斥鎖上等待的 Goroutine 個數(shù);


          2、Mutex 正常模式和饑餓模式正常模式(非公平鎖)


          正常模式下,所有等待鎖的 goroutine 按照 FIFO(先進先出)順序等待。喚醒的goroutine 不會直接擁有鎖,而是會和新請求鎖的 goroutine 競爭鎖的擁有。新請求鎖的 goroutine 具有優(yōu)勢:它正在 CPU 上執(zhí)行,而且可能有好幾個,所 以剛剛喚醒的 goroutine 有很大可能在鎖競爭中失敗。在這種情況下,這個被 喚醒的 goroutine 會加入到等待隊列的前面。如果一個等待的 goroutine 超過1ms 沒有獲取鎖,那么它將會把鎖轉(zhuǎn)變?yōu)轲囸I模式。


          饑餓模式(公平鎖)


          為了解決了等待 G 隊列的長尾問題
          饑餓模式下,直接由 unlock 把鎖交給等待隊列中排在第一位的 G(隊頭),同 時,饑餓模式下,新進來的 G 不會參與搶鎖也不會進入自旋狀態(tài),會直接進入 等待隊列的尾部,這樣很好的解決了老的 g 一直搶不到鎖的場景。饑餓模式的觸發(fā)條件,當一個 G 等待鎖時間超過 1 毫秒時,或者當前隊列只剩 下一個 g 的時候,Mutex 切換到饑餓模式。


          總結(jié)


          對于兩種模式,正常模式下的性能是最好的,goroutine 可以連續(xù)多次獲取 鎖,饑餓模式解決了取鎖公平的問題,但是性能會下降,其實是性能和公平的 一個平衡模式。


          3、Mutex 允許自旋的條件


          1 鎖已被占用,并且鎖不處于饑餓模式。
          2 積累的自旋次數(shù)小于最大自旋次數(shù)(active_spin=4)。3 cpu 核數(shù)大于 1。
          4 有空閑的 P。
          5 當前 goroutine 所掛載的 P 下,本地待運行隊列為空。

          4、RWMutex 實現(xiàn)


          通過記錄 readerCount 讀鎖的數(shù)量來進行控制,當有一個寫鎖的時候,會將讀 鎖數(shù)量設(shè)置為負數(shù) 1<<30。目的是讓新進入的讀鎖等待寫鎖之后釋放通知讀 鎖。同樣的寫鎖也會等等待之前的讀鎖都釋放完畢,才會開始進行后續(xù)的操 作。而等寫鎖釋放完之后,會將值重新加上 1<<30, 并通知剛才新進入的讀鎖(rw.readerSem),兩者互相限制。


          5、RWMutex 注意事項

          • RWMutex 是單寫多讀鎖,該鎖可以加多個讀鎖或者一個寫鎖

          • 讀鎖占用的情況下會阻止寫,不會阻止讀,多個goroutine 可以同時獲取讀鎖

          • 寫鎖會阻止其他 goroutine(無論讀和寫)進來,整個鎖由該 goroutine獨占

          • 適用于讀多寫少的場景

          • RWMutex 類型變量的零值是一個未鎖定狀態(tài)的互斥鎖。

          • RWMutex 在首次被使用之后就不能再被拷貝。

          • RWMutex 的讀鎖或?qū)戞i在未鎖定狀態(tài),解鎖操作都會引發(fā) panic。

          • RWMutex 的一個寫鎖?Lock?去鎖定臨界區(qū)的共享資源,如果臨界區(qū)的共享資源已被(讀鎖或?qū)戞i)鎖定,這個寫鎖操作的 goroutine 將被阻塞直到解鎖。

          • RWMutex 的讀鎖不要用于遞歸調(diào)用,比較容易產(chǎn)生死鎖。

          • RWMutex 的鎖定狀態(tài)與特定的 goroutine 沒有關(guān)聯(lián)。一個 goroutine 可以 RLock(Lock),另一個 goroutine 可以 RUnlock(Unlock)。

          • 寫鎖被解鎖后,所有因操作鎖定讀鎖而被阻塞的 goroutine 會被喚醒,并都可以成功鎖定讀鎖。

          • 讀鎖被解鎖后,在沒有被其他讀鎖鎖定的前提下,所有因操作鎖定寫鎖而被阻塞的 goroutine,其中等待時間最長的一個 goroutine 會被喚醒。


          6、Cond 是什么


          Cond 實現(xiàn)了一種條件變量,可以使用在多個 Reader 等待共享資源 ready 的場 景(如果只有一讀一寫,一個鎖或者 channel 就搞定了)
          每個 Cond 都會關(guān)聯(lián)一個 Lock(*sync.Mutex or *sync.RWMutex),當修改條 件或者調(diào)用 Wait 方法時,必須加鎖,保護 condition。


          7、Broadcast 和 Signal 區(qū)別


          ?func?(c?*Cond)?Broadcast()

          Broadcast 會喚醒所有等待 c 的 goroutine。

          調(diào)用 Broadcast 的時候,可以加鎖,也可以不加鎖。


          ??func?(c?*Cond)?Signal()


          Signal 只喚醒 1 個等待 c 的 goroutine。
          調(diào)用 Signal 的時候,可以加鎖,也可以不加鎖。


          8、Cond 中 Wait 使用


          ?func?(c?*Cond)?Wait()


          Wait()會自動釋放 c.L,并掛起調(diào)用者的 goroutine。之后恢復(fù)執(zhí)行,Wait()會 在返回時對 c.L 加鎖。
          除非被 Signal 或者 Broadcast 喚醒,否則 Wait()不會返回。
          由于 Wait()第一次恢復(fù)時,C.L 并沒有加鎖,所以當 Wait 返回時,調(diào)用者通常 并不能假設(shè)條件為真。


          取而代之的是, 調(diào)用者應(yīng)該在循環(huán)中調(diào)用 Wait。(簡單來說,只要想使用condition,就必須加鎖。)


          ?for?!condition()?{
          ????c.Wait()
          }
          ...?make?use?of?condition?...
          c.L.Unlock()
          c.L.Lock()


          9、WaitGroup 用法


          一個 WaitGroup 對象可以等待一組協(xié)程結(jié)束。使用方法是:
          1. main 協(xié)程通過調(diào)用?wg.Add(delta int)?設(shè)置 worker 協(xié)程的個數(shù),然后創(chuàng) 建 worker 協(xié)程;
          2.worker 協(xié)程執(zhí)行結(jié)束以后,都要調(diào)用?wg.Done();

          3.main 協(xié)程調(diào)用?wg.Wait()?且被 block,直到所有 worker 協(xié)程全部執(zhí)行結(jié)束 后返回。


          10、WaitGroup 實現(xiàn)原理

          • WaitGroup 主要維護了 2 個計數(shù)器,一個是請求計數(shù)器 v,一個是等待計數(shù) 器 w,二者組成一個 64bit 的值,請求計數(shù)器占高 32bit,等待計數(shù)器占低32bit。

          • 每次Add執(zhí)行,請求計數(shù)器v加1,Done方法執(zhí)行,請求計數(shù)器減1,v為0 時通過信號量喚醒 Wait()。


          11、什么是 sync.Once

          • Once 可以用來執(zhí)行且僅僅執(zhí)行一次動作,常常用于單例對象的初始化場 景。

          • Once 常常用來初始化單例資源,或者并發(fā)訪問只需初始化一次的共享資 源,或者在測試的時候初始化一次測試資源。

          • sync.Once 只暴露了一個方法 Do,你可以多次調(diào)用 Do 方法,但是只有第 一次調(diào)用 Do 方法時 f 參數(shù)才會執(zhí)行,這里的 f 是一個無參數(shù)無返回值 的函數(shù)。

          12、什么操作叫做原子操作
          一個或者多個操作在 CPU 執(zhí)行過程中不被中斷的特性,稱為原子性(atomicity)。這些操作對外表現(xiàn)成一個不可分割的整體,他們要么都執(zhí)行,要 么都不執(zhí)行,外界不會看到他們只執(zhí)行到一半的狀態(tài)。而在現(xiàn)實世界中,CPU不可能不中斷的執(zhí)行一系列操作,但如果我們在執(zhí)行多個操作時,能讓他們的 中間狀態(tài)對外不可見,那我們就可以宣城他們擁有了“不可分割”的原子性。
          在 Go 中,一條普通的賦值語句其實不是一個原子操作。列如,在 32 位機器上 寫 int64 類型的變量就會有中間狀態(tài),因為他會被拆成兩次寫操作(MOV)——寫 低32位和寫高32位。


          13、原子操作和鎖的區(qū)別


          原子操作由底層硬件支持,而鎖則由操作系統(tǒng)的調(diào)度器實現(xiàn)。鎖應(yīng)當用來保護 一段邏輯,對于一個變量更新的保護,原子操作通常會更有效率,并且更能利 用計算機多核的優(yōu)勢,如果要更新的是一個復(fù)合對象,則應(yīng)當使用atomic.Value 封裝好的實現(xiàn)。


          14、什么是 CAS


          CAS 的全稱為 Compare And Swap,直譯就是比較交換。是一條 CPU 的原子指 令,其作用是讓 CPU 先進行比較兩個值是否相等,然后原子地更新某個位置的 值,其實現(xiàn)方式是給予硬件平臺的匯編指令,在 intel 的 CPU 中,使用的cmpxchg 指令,就是說 CAS 是靠硬件實現(xiàn)的,從而在硬件層面提升效率。


          簡述過程是這樣:


          假設(shè)包含 3 個參數(shù)內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。V 表示要更新變量的 值,E 表示預(yù)期值,N 表示新值。僅當 V 值等于 E 值時,才會將 V 的值設(shè)為 N, 如果 V 值和 E 值不同,則說明已經(jīng)有其他線程在做更新,則當前線程什么都不 做,最后 CAS 返回當前 V 的真實值。CAS 操作時抱著樂觀的態(tài)度進行的,它總 是認為自己可以成功完成操作。基于這樣的原理,CAS 操作即使沒有鎖,也可 以發(fā)現(xiàn)其他線程對于當前線程的干擾。


          15、sync.Pool 有什么用


          對于很多需要重復(fù)分配、回收內(nèi)存的地方,sync.Pool 是一個很好的選擇。頻 繁地分配、回收內(nèi)存會給 GC 帶來一定的負擔,嚴重的時候會引起 CPU 的毛 刺,而 sync.Pool 可以將暫時不用的對象緩存起來,待下次需要的時候直接 使用,不用再次經(jīng)過內(nèi)存分配,復(fù)用對象的內(nèi)存,減輕 GC 的壓力,提升系統(tǒng) 的性能。


          最后:

          點擊下方名片鏈接,關(guān)注 「碼農(nóng)編程進階筆記?」微信公眾號,在微信聊天對話框回復(fù)「go語言實戰(zhàn)」「goweb編程」或者直接長按左下圖海報中的二維碼,可獲取最新golang電子書和視頻資源

          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  十八毛片| 老黄色人人 | 北条麻纪无码中文字幕 | 特色特污在线免费观看 | www.1区2区 |