<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Qt中文文檔-同步線程

          共 2102字,需瀏覽 5分鐘

           ·

          2020-10-05 12:00


          本篇文章來自項目?

          QtDocumentCN.


          https://github.com/QtDocumentCN/QtDocumentCN


          文章協(xié)議


          https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh





          同步線程

          盡管線程的初衷是讓代碼并行運行,仍然有許多時候,線程必須停下來等待其他線程。例如,若有兩個線程嘗試同時寫入同一個變量,則結(jié)果是不確定的。讓線程強制等待另外線程,這樣的機制被稱為互斥,是一種保護共享資源(如數(shù)據(jù))的常用技術。

          Qt 在為線程同步提供高級機制的同時,也提供了低級原語。

          低級同步原語

          QMutex 是能夠進行強制互斥的基礎類。為了獲取對一個共享資源的訪問權,線程會鎖住一個互斥鎖。若此時,另一個線程嘗試再次加鎖,則導致后者進入睡眠狀態(tài),直到第一個線程完成任務并解開互斥鎖。

          QReadWriteLock 類似 QMutex ,只是前者區(qū)分了“讀”與“寫”的訪問權限。當一段數(shù)據(jù)未處于寫入過程中時,多個線程可以安全地同時讀取它。QMutex 能強制多個線程輪流訪問共享數(shù)據(jù),而 QReadWriteLock 允許同時讀取,提高了并行性。

          QSemaphore 是 QMutex 的泛化,它保護一定數(shù)量的同類資源。QMutex 則與之相反,僅保護一個資源。信號量示例 是 QSemaphore 的一個使用典例:同步訪問在生產(chǎn)者和使用者之間的循環(huán)緩沖區(qū)。

          QWaitCondition 不同于強制互斥,它提供一個 條件變量 來同步線程。不同于其他原語令線程等待至資源解鎖,QWaitCondition 可以讓線程在符合特定條件時退出等待。為了讓等待中的線程繼續(xù)執(zhí)行,調(diào)用 wakeOne() 來隨機喚醒一個線程,或者調(diào)用 wakeAll() 來同時喚醒所有線程。等待條件示例 將告訴您如何使用 QWaitCondition 取代 QSemaphore 來解決生產(chǎn)者-消費者問題。

          注意:Qt 的同步類依賴于使用正確對齊的指針。例如,您不能在 MSVC 中使用打包類。(譯者注:即使用 #pragma pack 或 alignas 等方式非常規(guī)對齊地存儲同步類對象)

          這些線程同步類能讓一個方法做到線程安全。不過,這會導致性能損失,因此大多數(shù) Qt 的方法都不保障線程安全。


          風險

          如果一個線程鎖定了一個資源,卻在沒有使用完畢后解鎖它,則可能會導致程序凍結(jié),因為其他線程將永遠無法訪問該資源。這很容易出現(xiàn)在,例如,有異常拋出,并強制當前函數(shù)返回,而沒有釋放鎖的場景中。(譯者注:異常拋出時,當前函數(shù)會被強制就地返回,本地棧變量會被釋放。因此在引發(fā)異常的代碼之后的 unlock() 不會被執(zhí)行)

          另一個類似的場景是 死鎖 。例如,假設線程 A 正在等待線程 B 解鎖一個資源。若此時線程 B 也在等待線程 A 解鎖另一個資源,那么兩個線程持續(xù)相互等待,這將造成程序凍結(jié)。


          提供便利的類

          QMutexLocker、QReadLocker 與 QWriteLocker 使得 QMutex 與 QReadWriteLock 使用起來更加簡單。這些類會在它們構(gòu)造時鎖定資源,在析構(gòu)時自動解鎖資源。設計它們的初衷是簡化使用 QMutex 與 QReadWriteLock 的代碼,降低資源被意外永久鎖定的可能性。(譯者注:此方式可以保證線程安全,即在拋出異常,導致函數(shù)強制返回時,鎖會因為本地的 locker 棧對象析構(gòu)而被自動解鎖)

          高級事件隊列

          Qt 的 事件系統(tǒng) 在跨線程通信中非常有用。每個線程都有自己的事件循環(huán)。要令槽函數(shù)(或任何可動態(tài)調(diào)用的方法)在另一個線程中被調(diào)用,可將該調(diào)用目標置入目標線程的事件循環(huán)中。這可讓目標線程完成當前任務后再執(zhí)行槽函數(shù),而原始線程繼續(xù)并行運行。

          若要將調(diào)用代碼置于事件循環(huán)中,可創(chuàng)建一個隊列 信號槽 連接。每當發(fā)出信號時,事件系統(tǒng)將記錄它的參數(shù)。該信號接收者 所屬 的線程將會執(zhí)行對應的槽函數(shù)。此外,也可以使用 QMetaObject::invokeMethod() 以達到同樣效果,同時無需發(fā)射信號。在這兩種情況下,都必須使用 隊列連接,因為 直接連接 會繞過事件系統(tǒng),在當前線程中立刻執(zhí)行該方法。

          不同于使用低級原語,使用事件系統(tǒng)進行線程同步?jīng)]有死鎖的風險。不過,事件系統(tǒng)不會強制執(zhí)行互斥。如果可動態(tài)調(diào)用的方法訪問共享數(shù)據(jù),則依然需要使用低級原語對其進行保護。

          即便如此,Qt 的事件系統(tǒng)以及 隱式共享 的數(shù)據(jù)結(jié)構(gòu)依然提供了傳統(tǒng)線程鎖定的替代方案。如果僅使用信號槽,而且線程間無共享變量,多線程程序完全可以不使用低級原語。



          小程序


          Qt中文文檔



          參與項目



          歡迎各位參與我們的項目


          參與方式見下方鏈接


          QtDocumentCN項目組招人





          ------------------------

          長按下方二維碼關注




          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本五十路の浓厚交尾 | 东京热精品 | 亚洲无码小说 | 国产极品无码AV在线观看 | 黄色国产a片 |