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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                在Go中最常見的就是通信順序進程(Communicating sequential processes,CSP)的并發模型,通過共享通信,來實現共享內存,這里就提到了channel. Goroutine 和 Channel 分別對應 CSP 中的實體和傳遞信息的媒介,Go 語言中的 Goroutine 會通過 Channel 傳遞數據。 [![](https://github.com/KeKe-Li/data-structures-questions/raw/master/src/images/139.jpg)](https://github.com/KeKe-Li/data-structures-questions/blob/master/src/images/139.jpg) Goroutine通過使用channel傳遞數據,一個會向 Channel 中發送數據,另一個會從 Channel 中接收數據,它們兩者能夠獨立運行并不存在直接關聯,但是能通過 Channel 間接完成通信。 Channel 收發操作均遵循了先入先出(FIFO)的設計,具體規則如下: * 先從 Channel 讀取數據的 Goroutine 會先接收到數據; * 先向 Channel 發送數據的 Goroutine 會得到先發送數據的權利; Channel 通常會有以下三種類型: * 同步 Channel — 不需要緩沖區,發送方會直接將數據交給(Handoff)接收方; * 異步 Channel — 基于環形緩存的傳統生產者消費者模型; * `chan struct{}`類型的異步`Channel`的`struct{}`類型不占用內存空間,不需要實現緩沖區和直接發送(Handoff)的語義; Channel 在運行時使用`runtime.hchan`結構體表示: ~~~go type hchan struct { qcount uint // 當前隊列里還剩余元素個數 dataqsiz uint // 環形隊列長度,即緩沖區的大小,即make(chan T,N) 中的N buf unsafe.Pointer // 環形隊列指針 elemsize uint16 // 每個元素的大小 closed uint32 // 標識當前通道是否處于關閉狀態,創建通道后,該字段設置0,即打開通道;通道調用close將其設置為1,通道關閉 elemtype *_type // 元素類型,用于數據傳遞過程中的賦值 sendx uint // 環形緩沖區的狀態字段,它只是緩沖區的當前索引-支持數組,它可以從中發送數據 recvx uint // 環形緩沖區的狀態字段,它只是緩沖區當前索引-支持數組,它可以從中接受數據 recvq waitq // 等待讀消息的goroutine隊列 sendq waitq // 等待寫消息的goroutine隊列 // lock protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. // // Do not change another G's status while holding this lock // (in particular, do not ready a G), as this can deadlock // with stack shrinking. lock mutex // 互斥鎖,為每個讀寫操作鎖定通道,因為發送和接受必須是互斥操作 } type waitq struct { first *sudog last *sudog } ~~~ 其中hchan結構體中有五個字段是構建底層的循環隊列: ~~~go * qcount — Channel 中的元素個數; * dataqsiz — Channel 中的循環隊列的長度; * buf — Channel 的緩沖區數據指針; * sendx — Channel 的發送操作處理到的位置; * recvx — Channel 的接收操作處理到的位置; ~~~ 通常,`elemsize`和`elemtype`分別表示當前 Channel 能夠收發的元素類型和大小. `sendq`和`recvq`存儲了當前 Channel 由于緩沖區空間不足而阻塞的 Goroutine 列表,這些等待隊列使用雙向鏈表`runtime.waitq`表示,鏈表中所有的元素都是`runtime.sudog`結構. `waitq`表示一個在等待列表中的 Goroutine,該結構體中存儲了阻塞的相關信息以及兩個分別指向前后`runtime.sudog`的指針。 channel 在Go中是通過make關鍵字創建,編譯器會將make(chan int,10). 創建管道: `runtime.makechan`和`runtime.makechan64`會根據傳入的參數類型和緩沖區大小創建一個新的 Channel 結構,其中后者用于處理緩沖區大小大于 2 的 32 次方的情況. 這里我們來詳細看下`makechan`函數: ~~~go func makechan(t *chantype, size int) *hchan { elem := t.elem // compiler checks this but be safe. if elem.size >= 1<<16 { throw("makechan: invalid channel element type") } if hchanSize%maxAlign != 0 || elem.align > maxAlign { throw("makechan: bad alignment") } mem, overflow := math.MulUintptr(elem.size, uintptr(size)) if overflow || mem > maxAlloc-hchanSize || size < 0 { panic(plainError("makechan: size out of range")) } // Hchan does not contain pointers interesting for GC when elements stored in buf do not contain pointers. // buf points into the same allocation, elemtype is persistent. // SudoG's are referenced from their owning thread so they can't be collected. // TODO(dvyukov,rlh): Rethink when collector can move allocated objects. var c *hchan switch { case mem == 0: // Queue or element size is zero. c = (*hchan)(mallocgc(hchanSize, nil, true)) // Race detector uses this location for synchronization. c.buf = c.raceaddr() case elem.ptrdata == 0: // Elements do not contain pointers. // Allocate hchan and buf in one call. c = (*hchan)(mallocgc(hchanSize+mem, nil, true)) c.buf = add(unsafe.Pointer(c), hchanSize) default: // Elements contain pointers. c = new(hchan) c.buf = mallocgc(mem, elem, true) } c.elemsize = uint16(elem.size) c.elemtype = elem c.dataqsiz = uint(size) lockInit(&c.lock, lockRankHchan) if debugChan { print("makechan: chan=", c, "; elemsize=", elem.size, "; dataqsiz=", size, "\n") } return c } ~~~ Channel 中根據收發元素的類型和緩沖區的大小初始化`runtime.hchan`結構體和緩沖區: [![](https://github.com/KeKe-Li/data-structures-questions/raw/master/src/images/134.jpg)](https://github.com/KeKe-Li/data-structures-questions/blob/master/src/images/134.jpg) arena區域就是我們所謂的堆區,Go動態分配的內存都是在這個區域,它把內存分割成8KB大小的頁,一些頁組合起來稱為mspan。 bitmap區域標識arena區域哪些地址保存了對象,并且用4bit標志位表示對象是否包含指針、GC標記信息。bitmap中一個byte大小的內存對應arena區域中4個指針大小(指針大小為 8B )的內存,所以bitmap區域的大小是512GB/(4\*8B)=16GB。 [![](https://github.com/KeKe-Li/data-structures-questions/raw/master/src/images/135.jpg)](https://github.com/KeKe-Li/data-structures-questions/blob/master/src/images/135.jpg) [![](https://github.com/KeKe-Li/data-structures-questions/raw/master/src/images/136.jpg)](https://github.com/KeKe-Li/data-structures-questions/blob/master/src/images/136.jpg) 此外我們還可以看到bitmap的高地址部分指向arena區域的低地址部分,這里bitmap的地址是由高地址向低地址增長的。 spans區域存放mspan(是一些arena分割的頁組合起來的內存管理基本單元,后文會再講)的指針,每個指針對應一頁,所以spans區域的大小就是512GB/8KB\*8B=512MB。 除以8KB是計算arena區域的頁數,而最后乘以8是計算spans區域所有指針的大小。創建mspan的時候,按頁填充對應的spans區域,在回收object時,根據地址很容易就能找到它所屬的mspan。
                  <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>

                              哎呀哎呀视频在线观看