<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                活鎖是正在主動執行并發操作的程序,但這些操作無法向前移動程序的狀態。 你有沒有在走廊走向另一個人? 她移動到一邊讓你通過,但你也是這樣做的。 所以你轉移到另一邊,但她也是這樣做的。 想象這會永遠持續下去,這就是活鎖。 接下來的這個例子,我不建議試圖了解它的細節,直到你牢牢掌握sync包。 相反,我建議遵循代碼標注來理解高亮,然后將注意力轉移到包含示例核心的第二個代碼塊。 ``` cadence := sync.NewCond(&sync.Mutex{}) go func() { for range time.Tick(1 * time.Millisecond) { cadence.Broadcast() } }() takeStep := func() { cadence.L.Lock() cadence.Wait() cadence.L.Unlock() } tryDir := func(dirName string, dir *int32, out *bytes.Buffer) bool { //1 fmt.Fprintf(out, " %v", dirName) atomic.AddInt32(dir, 1) //2 takeStep() //3 if atomic.LoadInt32(dir) == 1 { fmt.Fprint(out, ". Success!") return true } takeStep() atomic.AddInt32(dir, -1) //4 return false } var left, right int32 tryLeft := func(out *bytes.Buffer) bool { return tryDir("left", &left, out) } tryRight := func(out *bytes.Buffer) bool { return tryDir("right", &right, out) } ``` 1. tryDir 允許一個人嘗試向某個方向移動并返回,無論他們是否成功。 每個方向都表示為試圖朝這個方向移動的次數。 2. 首先,我們通過將該方向遞增1來朝著某個方向移動。 我們將在第3章詳細討論atomic包。現在,你只需要知道這個包的操作是原子操作。 3. 每個人必須以相同的速度或節奏移動。 takeStep模擬所有動作之間的恒定節奏。 4. 在這里,這個人意識到他們不能在這個方向上放棄。 我們通過將該方向遞減1來表示這一點。 ``` walk := func(walking *sync.WaitGroup, name string) { var out bytes.Buffer defer func() { fmt.Println(out.String()) }() defer walking.Done() fmt.Fprintf(&out, "%v is trying to scoot:", name) for i := 0; i < 5; i++ { //1 if tryLeft(&out) || tryRight(&out) { //2 return } } fmt.Fprintf(&out, "\n%v tosses her hands up in exasperation!", name) } var peopleInHallway sync.WaitGroup //3 peopleInHallway.Add(2) go walk(&peopleInHallway, "Alice") go walk(&peopleInHallway, "Barbara") peopleInHallway.Wait() ``` 1. 我對嘗試次數進行了人為限制,以便該程序結束。 在一個有活鎖的程序中,可能沒有這種限制,這就是為什么它是一個現實工作中的問題。 2. 首先,這個人會試圖向左走,如果失敗了,會嘗試向右走。 3. 這個變量為程序提供了等待,直到兩個人都能夠相互通過或放棄。 程序會產生如下輸出: ``` Alice is trying to scoot: left right left right left right left right left right Alice tosses her hands up in exasperation! Barbara is trying to scoot: left right left right left right left right left right Barbara tosses her hands up in exasperation! ``` 你可以看到Alice和Barbara在最終放棄之前持續交互。 這個例子演示了一個非常常見的活鎖寫入原因:兩個或多個并發進程試圖在沒有協調的情況下防止死鎖。 如果走廊里的人們一致認為只有一個人會移動,那么就不會有活鎖:一個人靜止不動,另一個人移動到另一邊,他們會繼續走路。 在我看來,活鎖比死鎖更難以發現,因為它看起來好像程序正在工作。 如果活鎖程序在你的機器上運行,并且你查看了CPU利用率以確定它是否在執行任何操作,那么你可能會認為它是。 根據活鎖的不同,它甚至可能會發出其他信號,使你認為它正在工作。 然而,一直以來,你的程序都扮演著走廊洗牌的永恒游戲。 活鎖是饑餓的問題的一個子集。 接下來我們會討論。 * * * * * 學識淺薄,錯誤在所難免。我是長風,歡迎來Golang中國的群(211938256)就本書提出修改意見。
                  <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>

                              哎呀哎呀视频在线观看