<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                死鎖是所有并發進程都在彼此等待的狀態。 在這種情況下,如果沒有外部干預,程序將永遠不會恢復。 如果這聽起來很嚴峻,那是因為它確實很嚴峻! Go運行時會檢測到一些死鎖(所有的例程必須被阻塞或“休眠”),但這對于幫助你防止死鎖產生沒有多大幫助。 為了幫助你更直觀的認識死鎖,我們先來看一個例子。同樣的,跟著注釋走,任何變量、函數、語句都不重要: ``` type value struct { mu sync.Mutex value int } var wg sync.WaitGroup printSum := func(v1, v2 *value) { defer wg.Done() v1.mu.Lock() //1 defer v1.mu.Unlock() //2 time.Sleep(2 * time.Second) //3 v2.mu.Lock() defer v2.mu.Unlock() fmt.Printf("sum=%v\n", v1.value+v2.value) } var a, b value wg.Add(2) go printSum(&a, &b) go printSum(&b, &a) wg.Wait() ``` 1. 這里我們試圖訪問帶鎖的部分 2. 這里我們試圖調用defer關鍵字釋放鎖 3. 這里我們添加休眠時間 以造成死鎖 如果你試著運行這段程序,應該會看到這樣的輸出: ``` fatal error: all goroutines are asleep - deadlock! ``` 為什么? 如果仔細觀察,你將在此代碼中看到計時問題。下面的時序圖能清晰的展現問題所在: :-: ![死鎖時序圖](https://box.kancloud.cn/b3afc3ec1b64f6d2e1ab8047ee501829_482x156.png) 實質上,我們創建了兩個不能一起運轉的齒輪:我們的第一個打印總和調用a鎖定,然后嘗試鎖定b,但與此同時,我們打印總和的第二個調用鎖定了b并嘗試鎖定a。 兩個goroutine都無限地等待著彼此。 >為了保持這個例子簡單,我使用time.Sleep來觸發死鎖。 但是,這引入了競爭條件! 你能找到它嗎? >一個邏輯上“完美”的死鎖將需要正確的同步。 這似乎很明顯,為什么當我們以這種方式繪制圖表時出現這種僵局,但我們會從更嚴格的定義中受益。事實證明,出現僵局時必定存在一些條件,1971年,埃德加科夫曼在一篇論文中列舉了這些條件。這些條件現在稱為科夫曼條件,是幫助檢測,防止和糾正死鎖的技術基礎。 科夫曼條件如下: #### *相互排斥* 并發進程在任何時候都擁有資源的獨占權。 #### *等待條件* 并發進程必須同時持有資源并等待額外的資源。 #### *沒有搶占* 并發進程持有的資源只能由該進程釋放,因此它滿足了這種情況。 #### *循環等待* 并發進程(P1)等待并發進程(P2),同時P2也在等待P1,因此也符合"循環等待"這一條件。 :-: ![科夫曼條件](https://box.kancloud.cn/c290764bba3ed54f00f032741fdc47e5_386x144.png) 讓我們來看看我們的設計程序,并確定它是否符合所有四個條件: 1. printSum函數確實需要a和b的獨占權,所以它滿足了這個條件。 2. 因為printSum保持a或b并等待另一個,所以它滿足這個條件。 3. 我們沒有任何辦法讓我們的goroutine被搶占。 4. 我們第一次調用printSum正在等待我們的第二次調用,反之亦然。 很好,我們親手實現了死鎖。 科夫曼條件同樣有助于我們規避死鎖。如果我們確保至少有一個條件不成立,就可以防止發生死鎖。不幸的是,實際上這些條件很難推理,因此難以預防。網上大量充斥著被死鎖困擾的開發人員的求助,一旦有人指出它就很明顯,但通常需要另一雙眼睛。 * * * * * 學識淺薄,錯誤在所難免。我是長風,歡迎來Golang中國的群(211938256)就本書提出修改意見。 感謝beego群(258969317)的"赤腳大仙"提出"循環等待"部分的修改意見,文字已作調整。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看