<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之旅 廣告
                [TOC] ### **channel 是否線程安全?鎖用在什么地方?** 是線程安全的,channel的底層是一個hchan結構,里面加了mutex ~~~ type hchan struct { ...... lock mutex //互斥鎖,chan不允許并發讀寫 } ~~~ ### **go channel 的底層實現原理** ~~~ type hchan struct { qcount uint dataqsiz uint buf unsafe.Pointer elemsize uint16 closed uint32 elemtype *_type sendx uint recvx uint recvq waitq sendq waitq lock mutex //互斥鎖,chan不允許并發讀寫 } ~~~ qcount:channel里面的元素計數。內建函數 len 可以返回這個字段的值。已接收還沒被取走 dataqsiz:環形隊列大小,即可存放元素的個數。make(chan int,10),10就是這個值 buf:當 channel 設置了緩沖數量時,該 buf 指向一個存儲緩沖數據的區域,該區域是一個循環隊列的數據結構 elemsize :要發送或接收的數據類型大小 closed :標識關閉狀態 elemtype :元素類型 sendx :當 channel 設置了緩沖數量時,數據區域即循環隊列此時已發送數據的索引位置 recvx:當 channel 設置了緩沖數量時,數據區域即循環隊列此時已接收數據的索引位置 recvq :想讀取數據但又被阻塞住的 goroutine 隊列,即:等待讀消息的goroutine隊列 sendq :想發送數據但又被阻塞住的 goroutine 隊列,即:等待寫消息的goroutine隊列 ### **channel的特點** 2種類型:有緩沖、無緩沖 3種模式:雙向通道,只允許發送通道、只允許接收通道 3種狀態:未初始化(nil)、關閉、正常 | | nil | 關閉 | 正常 | | --- | --- | --- | --- | | 關閉 | panic | panic | 可以關閉 | | 發送 | 阻塞導致死鎖 | panic | 成功發送/阻塞 | | 接收 | 阻塞導致死鎖 | 緩沖區有值,讀值,沒有值,返回零值 | 成功接收/阻塞 | ### **向 channel 發送數據和從 channel 讀數據的流程是什么樣的?** **向 channel 寫數據:** 若等待接收隊列 recvq 不為空,無論緩沖區中無數據或無緩沖區,將直接從 recvq 取出 G ,并把數據寫入,最后把該 G 喚醒,結束發送過程。 若緩沖區中有空余位置,則將數據寫入緩沖區,結束發送過程。 若緩沖區中沒有空余位置,則將發送數據寫入 G,將當前 G 加入 sendq ,進入睡眠,等待被讀 goroutine 喚醒。 **從 channel 讀數據** 若等待發送隊列 sendq 不為空,且沒有緩沖區,直接從 sendq 中取出 G ,把 G 中數據讀出,最后把 G 喚醒,結束讀取過程。 如果等待發送隊列 sendq 不為空,緩沖區已滿,從緩沖區中首部讀出數據,把 G 中數據寫入緩沖區尾部,把 G 喚醒,結束讀取過程。 如果緩沖區中有數據,則從緩沖區取出數據,結束讀取過程。 如果緩沖區中沒有數據,將當前 goroutine 加入 recvq ,進入睡眠,等待被寫 goroutine 喚醒。 **關閉 channel** 1.關閉 channel 時會將 recvq 中的 G 全部喚醒,本該寫入 G 的數據位置為 nil。將 sendq 中的 G 全部喚醒,但是這些 G 會 panic。 ### **chan 使用場景** 消息傳遞、請求、響應轉發,任務分發,限流,同步與異步
                  <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>

                              哎呀哎呀视频在线观看