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

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 競爭條件 當我們能夠沒有辦法自信地確認一個事件是在另一個事件的前面或者后面發生的話,就說明x和y這兩個事件是并發的。 ## 并發安全 一個函數在線性程序中可以正確地工作。如果在**并發**的情況下,這個函數依然可以**正確地工作**的話,那么我們就說這個函數是并發安全的,并發安全的函數不需要額外的同步工作。我們可以把這個概念概括為一個特定類型的一些方法和操作函數,對于某個類型來說,如果其所有可訪問的**方法和操作都是并發安全**的話,那么類型便是**并發安全的。** ## 哪些是并發不安全的 導出包級別的函數一般情況下都是并發安全的。由于**package級的變量沒法被限制在單一的gorouine**,所以修改這些變量“必須”使用互斥條件。 也就是說,包級別的變量是并發不安全的,包括所有普通類型和slice,map,數組. ## 競爭條件 **競爭條件指的是程序在多個goroutine交叉執行操作時,沒有給出正確的結果**。競爭條件是很惡劣的一種場景,因為這種問題會一直潛伏在你的程序里,然后在非常少見的時候蹦出來,或許只是會在很大的負載時才會發生,又或許是會在使用了某一個編譯器、某一種平臺或者某一種架構的時候才會出現。這些使得**競爭條件帶來的問題非常難以復現而且難以分析診斷**。 ## 產生競爭條件的原因 所有對數據進行的操作,都會先拿到這個數據本身的值,然后再本身的值上面進行操作. 非并發情況下,肯定是順序執行的.但是在并發條件下A先讀S的值,此時B在A的后面也讀到S的值了,然后B在S上+100,A也在S上+100.然后S的值就是100.因為B對S的操作丟失了. ``` S := 0 A讀 //S = 0 B讀 //S = 0 B寫: S += 100 //S = 100 A寫: S += 100 //S = 100 S最后就等于100了,因為A和B都不是在對方已經+100的基礎上進行+100的.它們讀到的都是0. ``` ## 數據競爭(非常重要的概念) 無論任何時候,只要有**兩個或以上goroutine并發訪問同一變量**,且至少其中的一個是**寫操作**的時候就會發生數據競爭。 ## 一定要避免數據競爭 **一個好的經驗法則是根本就沒有什么所謂的良性數據競爭(不要心存幻想)**。 ## 避免數據競爭三種方式 ### 1.不去寫變量 對于共享數據,所有的并發只讀它,而不去修改它.(但是很多業務就是要寫啊,所以這個方式不好) ### 2.避免多個goroutine訪問變量 只能使用一個channel來發送給指定的goroutine請求來查詢更新變量。這也就是Go的口頭禪“不要使用共享數據來通信;使用通信來共享數據”。一個提供對一個指定的變量通過channel來請求的goroutine叫做這個變量的監控(monitor)goroutine。 下面的例子可以看的很清除,對于共享數據,專門使用一個goroutine來監控它數據操作的情況,所有的操作都是有順序的. **這里的秘密就在于,讀是可以隨便讀,而寫則通過channel來進行線性化.這樣就避免了數據競爭**. ~~~ package bank var deposits = make(chan int) // send amount to deposit var balances = make(chan int) // receive balance func Deposit(amount int) { deposits <- amount } func Balance() int { return <-balances } func teller() { var balance int // balance is confined to teller goroutine for { select { case amount := <-deposits: balance += amount case balances <- balance: } } } func init() { go teller() // start the monitor goroutine } ~~~ 即使**當一個變量無法在其整個生命周期內被綁定到一個獨立的goroutine**,綁定依然是并發問題的一個解決方案。例如在一條流水線上的goroutine之間共享變量是很普遍的行為,在這兩者間會通過channel來傳輸地址信息。如果流水線的每一個階段都能夠避免在將變量傳送到下一階段后再去訪問它,那么對這個變量的所有訪問就是線性的。其效果是變量會被綁定到流水線的一個階段,傳送完之后被綁定到下一個,以此類推。這種規則有時被稱為串行綁定。 怎么理解上面的話呢?就是可能一個變量是在函數中的,在函數內部使用了并發程序去操作它,那么依然是可以通過channel來將共享的變量綁定在一個channel上.那么這樣也是線性的.只要是在往這個channel發送該變量之前沒有再去使用它. ### 3.互斥 允許很多goroutine去訪問變量,但是在同一個時刻最多只有一個goroutine在訪問。這種方式被稱為“互斥”.
                  <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>

                              哎呀哎呀视频在线观看