那麼併發性是如何實現的呢?在單核cpu上並行工作是一種錯覺,有點類似於電影中移**像的錯覺。對於程序,這種錯覺是通過在很短的時間後中斷處理器在乙個程序上的工作而產生的。然後處理器轉到下一道工序。為了在程序之間切換,儲存當前的程式計數器並載入下乙個處理器的程式計數器。這是不夠的,因為同樣需要對暫存器、某些體系結構和作業系統特定的資料進行處理。
正如乙個cpu可以驅動兩個或多個程序一樣,也可以讓cpu執行在乙個程序的兩個不同**段上。當乙個程序啟動時,它總是執行乙個**段,因此這個程序被稱為有乙個執行緒。然而,程式可能決定啟動第二個執行緒。然後,在乙個程序內同時處理兩個不同的碼序列。通過重複儲存程式計數器和暫存器,然後載入下乙個執行緒的程式計數器和暫存器,在單核cpu上實現併發。在活動執行緒之間迴圈不需要程式的合作。當切換到下乙個執行緒時,乙個執行緒可能處於任何狀態。
當前cpu設計的趨勢是多核並存。典型的單執行緒應用程式只能使用乙個核心。然而,乙個具有多個執行緒的程式可以被分配到多個核上,使事情以真正併發的方式發生。因此,將工作分配給多個執行緒可以使程式在多核cpu上執行得更快,因為可以使用額外的核。
如前所述,每個程式在啟動時都有乙個執行緒。這個執行緒被稱為「主線程」(在qt應用程式中也稱為「gui執行緒」)。qt gui必須在這個執行緒中執行。所有小部件和幾個相關類(例如qpixmap)都不能在輔助線程中工作。輔助線程通常稱為「工作執行緒」,因為它用於從主線程解除安裝處理工作。
每個執行緒都有自己的堆疊,這意味著每個執行緒都有自己的呼叫歷史和區域性變數。與程序不同,執行緒共享相同的位址空間。下圖顯示了執行緒的構建塊是如何位於記憶體中的。非活動執行緒的程式計數器和暫存器通常儲存在核心空間中。每個執行緒都有乙個共享的**副本和乙個單獨的堆疊。
如果兩個執行緒有乙個指向同一物件的指標,那麼兩個執行緒可能會同時訪問該物件,這可能會破壞物件的完整性。很容易想象,當同乙個物件的兩個方法同時執行時,可能會出現許多問題。
有時需要從不同的執行緒訪問乙個物件;例如,生活在不同執行緒中的物件需要通訊時。由於執行緒使用相同的位址空間,因此執行緒交換資料比程序交換資料更容易、更快。資料不必序列化和複製。傳遞指標是可能的,但必須嚴格協調哪個執行緒接觸哪個物件。必須防止同時在乙個物件上執行操作。有幾種方法可以實現這一點,下面將介紹其中一些方法。
那麼什麼是安全的呢?在乙個執行緒中建立的所有物件都可以在該執行緒中安全地使用,前提是其他執行緒沒有對它們的引用,並且物件與其他執行緒沒有隱式耦合。這種隱式耦合可能發生在例項之間共享資料時,比如靜態成員、單例或全域性資料。熟悉執行緒安全類和可重入類和函式的概念。
執行緒基本上有兩個用例:
利用多核處理器提高處理速度。
通過解除安裝長時間持續的處理或阻塞對其他執行緒的呼叫來保持gui執行緒或其他時間關鍵執行緒的響應。
開發人員需要非常小心執行緒。啟動其他執行緒很容易,但很難確保所有共享資料保持一致。問題通常很難發現,因為它們可能只是偶爾出現,或者只在特定的硬體配置上出現。在建立執行緒來解決某些問題之前,應該考慮可能的替代方案。
供選擇的
注釋qeventloop::processevents()
在耗時的計算過程中反覆呼叫qeventloop::processevents()可以防止gui阻塞。但是,這個解決方案不能很好地擴充套件,因為根據硬體的不同,對processevents()的呼叫可能發生得太頻繁,或者不夠頻繁
qtimer
後台處理有時可以方便地使用乙個計時器來排程乙個插槽在未來的某個時間點的執行。間隔為0的計時器一旦不再有需要處理的事件就會超時。
qsocketnotifier qnetworkaccessmanager qiodevice::readyread()
這是一種替代使用乙個或多個執行緒(每個執行緒在慢速網路連線上阻塞讀取)的方法。只要可以快速執行響應大量網路資料的計算,這種響應式設計就比執行緒中的同步等待更好。與執行緒設計相比,反應式設計更不容易出錯,而且節能。在許多情況下也有效能優勢。
一般來說,建議只使用安全且經過測試的路徑,並避免引入特殊執行緒概念。
qtconcurrent模組提供了乙個簡單的介面,可以將工作分配到所有處理器的核心上。執行緒**完全隱藏在qtconcurrent框架中,所以您不需要考慮細節。然而,當需要與正在執行的執行緒通訊時,qtconcurrent不能被使用,它不應該被用於處理阻塞操作。
參考:以下各節介紹 qobjects 如何與執行緒互動,程式如何安全地訪問來自多個執行緒的資料,以及非同步執行如何在不阻塞執行緒的情況下生成結果。
如上所述,開發人員在從其他執行緒呼叫物件的方法時必須始終小心謹慎。執行緒相關性不會更改這種情況。
qt文件將幾個方法標記為執行緒安全的。postevent()是乙個值得注意的例子。執行緒安全的方法可以從不同的執行緒同時呼叫。
在通常沒有併發訪問方法的情況下,在發生併發訪問之前,呼叫其他執行緒中物件的非執行緒安全方法可能會工作數千次,從而導致意外的行為。編寫測試**並不能完全確保執行緒的正確性,但這仍然很重要。在linux上,valgrind和helgrind可以幫助檢測線程錯誤。
在編寫多執行緒應用程式時,必須格外小心,以避免資料損壞。有關如何安全地使用執行緒的討論,參閱同步執行緒。
獲取輔助線程結果的乙個方法就是等待執行緒終止。但是,在許多情況下,阻止等待是不能接受的。阻塞等待的另一種選擇是非同步的結果交付,使用的是已發布的事件或排隊的訊號和槽。這將產生一定的開銷,因為操作的結果不會出現在下乙個源**行中,而是出現在原始檔中其他位置的乙個槽中。qt開發人員習慣於處理這種非同步行為,因為它與gui應用程式中使用的事件驅動程式設計非常相似。
Qt 執行緒 00 執行緒基礎知識 官翻
那麼併發是如何實現的呢?在單核cpu上並行工作是一種錯覺,有點類似於電影中移 像的錯覺。對於程序來說,在很短的時間後中斷處理器在乙個程序上的工作就會產生錯覺。然後處理器繼續下乙個程序。為了在程序之間進行切換,當前程式計數器被儲存,下乙個處理器的程式計數器被載入。這還不夠,因為需要對暫存器 特定體系結...
QT學習 基礎知識
qt把它所支援的平台分兩級,第一級是重點支援的,第二級次之 第一級平台 platform compilers linux 32 and 64 bit gcc 4.2 microsoft windows xp gcc 4.4 mingw 32 bit msvc 2003,2005 32 and 64 ...
Qt基礎知識小結
1 pro與.pri檔案 pri檔案跟pro檔案沒有本質區別,都是起到包含路徑等作用,區別在於pro檔案是主要檔案,pri是附屬檔案。下面是解釋 如果有幾個工程檔案需要共享相同的項,則可以把相同的項提取到單獨的檔案中,在各自的pro檔案中使用include 語句包含它們。通常,打算被別的工程檔案包含...