<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國際加速解決方案。 廣告
                # Swoole4 協程與 Go 協程有哪些區別 [TOC] `Swoole4`與`Go`協程在設計上是完全一致的,均是`stackful`的,每個協程擁有獨立的運行棧。協程調度器使用匯編代碼,切換協程上下文。 `Swoole4`與`Go`協程在實現細節上存在一些差異。主要是以下幾方面: ## 多線程 * `Swoole4`的協程調度器是單線程的,因此不存在數據同步問題,同一時間只會有一個協程在運行 * `Go`協程調度器是多線程的,同一時間可能會有多個協程同時執行 因此在`Swoole4`協程中操作全局變量是不需要加鎖的。而`Go`的程序由于依然是類似`Java`的多線程模式,因此務必要對臨界資源加鎖,避免出現數據同步問題。或者使用官方`sync`包提供的各種并發容器。 實際上`Go`的`chan`和并發容器,底層仍然使用了`Mutex`進行鎖操作,鎖的爭搶是普遍存在的。 `Swoole4`由于是單線程多進程的,底層沒有使用任何`Mutex`鎖,不存在鎖的爭搶。 同樣帶來的問題是,沒有超全局變量。只有進程級全局變量,讀寫`PHP`全局變量只在當前進程內有效。如果希望多進程共享數據,有`3`種解決方案: * 使用`Table`和`Atomic`對象,或者其他共享內存數據結構 * 使用`IPC`進程間通信 * 借助存儲實現數據的共享和中轉,如`Redis`、`MySQL`或`文件操作` ## Defer `Swoole4`提供的`defer`關鍵詞與`Go`的`defer`存在差異。 `Go`的`defer`是綁定函數的,在當前函數退出時會執行`defer`任務。這是由于`Go`沒有析構函數,可能會出現資源泄漏。而`PHP`是有析構函數的,所有資源類對象,析構時會自動釋放。 #### Go ~~~ func test() { db := new(database) close := db.connect() defer close() fmt.Println("query db...") } ~~~ 由于`db`對象在`gc`時僅釋放內存,沒有對應的析構函數釋放連接資源,可能會產生資源泄漏。因此需要增加`defer`任務關閉連接釋放資源。 #### PHP ~~~ function test() { $db = new Database; $db->connect('127.0.0.1', 6379); $db->query($sql); } ~~~ 上面代碼不會產生資源泄漏,因為`PHP`有基于引用計數的`gc`和析構函數,在函數退出時,`db`對象銷毀,析構函數中會自動執行`$db->close()`。使用`defer`反而是多次一舉。 ~~~ function () { $db = new Database; $db->connect('127.0.0.1', 6379); $db->query($sql); defer(function () use ($db) { $db->close(); }); } ~~~ * 函數退出時,`$db`對象被`defer`引用了,因此不會析構 * `defer`任務執行完畢,引用解除,對象析構。在析構方法中,因為連接已關閉,不會再執行`$db->close()` `Swoole4`的`defer`設計為**在協程退出時一起執行**,在多層函數調用嵌套中添加大量`defer`任務,與`Coroutine`是綁定的。在這個`Coroutine`結束時,會按照先進后出的順序,執行`defer`任務。 ## 共用 Socket 資源 在`Go`的程序中,可以多個協程同時并發地去讀同一個`Socket`,底層完成了協程的排隊和調度。 **這要求開發者清楚自己的行為,否則可能會產生邏輯錯誤。** #### Go ~~~ func test() { db := new(database) close := db.connect() go func(db) { db.query(sql); } (db); go func(db) { db.query(sql); } (db); } ~~~ `Go`是允許這樣操作的,實際上這個可能會存在嚴重問題。`socket`讀寫操作產生并發,可能產生數據包錯亂。 `Swoole`中禁止了這種行為。不允許多個協程同時讀取同一個`Socket`。否則會產生致命錯誤。 #### PHP ~~~ function test() { $db = new Database; $db->connect('127.0.0.1', 6379); go(function () use ($db) { $db->query($sql); }); go(function () use ($db) { $db->query($sql); }); } ~~~ 以上代碼中有`2`個協程同時操作`$db`對象,可能會產生嚴重錯誤。底層會直接拋出致命錯誤,錯誤信息為: ~~~ "%s has already been bound to another coroutine#%ld, reading or writing of the same socket in multiple coroutines at the same time is not allowed." ~~~ 錯誤碼:`SW_ERROR_CO_HAS_BEEN_BOUND` **使用`Channel`或`SplQueue`實現連接池,管理資源對象,就可以很好地解決此問題。**
                  <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>

                              哎呀哎呀视频在线观看