Qt多線程學(xué)習(xí)之路(1)
本文2018年記錄,2019929嘗試使用B站文章作記錄博客
本文記錄Qt/C++多線程學(xué)習(xí)中不斷踩到的坑,謹(jǐn)作個(gè)人學(xué)習(xí)備份記錄,如有不當(dāng)請(qǐng)指正
首發(fā)于個(gè)人博客dksoft.site
學(xué)習(xí)線程前需要了解兩個(gè)術(shù)語(yǔ):
?
§? 可重入的(Reentrant):如果多個(gè)線程可以在同一時(shí)刻調(diào)用一個(gè)類的所有函數(shù),并且保證每一次函數(shù)調(diào)用都引用一個(gè)唯一的數(shù)據(jù),就稱這個(gè)類是可重入的(Reentrant means that all the functions in the referenced class can be called simultaneously by multiple threads, provided that each invocation of the functions reference unique data.)。大多數(shù) C++ 類都是可重入的。類似的,一個(gè)函數(shù)被稱為可重入的,如果該函數(shù)允許多個(gè)線程在同一時(shí)刻調(diào)用,而每一次的調(diào)用都只能使用其獨(dú)有的數(shù)據(jù)。全局變量就不是函數(shù)獨(dú)有的數(shù)據(jù),而是共享的。換句話說,這意味著類或者函數(shù)的使用者必須使用某種額外的機(jī)制(比如鎖)來控制對(duì)對(duì)象的實(shí)例或共享數(shù)據(jù)的序列化訪問。
?
§? 線程安全(Thread-safe):如果多個(gè)線程可以在同一時(shí)刻調(diào)用一個(gè)類的所有函數(shù),即使每一次函數(shù)調(diào)用都引用一個(gè)共享的數(shù)據(jù),就說這個(gè)類是線程安全的(Threadsafe means that all the functions in the referenced class can be called simultaneously by multiple threads even when each invocation references shared data.)。如果多個(gè)線程可以在同一時(shí)刻訪問函數(shù)的共享數(shù)據(jù),就稱這個(gè)函數(shù)是線程安全的。
?
?
§? Qt::DirectConnection:直接連接意味著槽函數(shù)將在信號(hào)發(fā)出的線程直接調(diào)用
§? Qt::QueuedConnection:隊(duì)列連接意味著向接受者所在線程發(fā)送一個(gè)事件,該線程的事件循環(huán)將獲得這個(gè)事件,然后之后的某個(gè)時(shí)刻調(diào)用槽函數(shù)
§? Qt::BlockingQueuedConnection:阻塞的隊(duì)列連接就像隊(duì)列連接,但是發(fā)送者線程將會(huì)阻塞,直到接受者所在線程的事件循環(huán)獲得這個(gè)事件,槽函數(shù)被調(diào)用之后,函數(shù)才會(huì)返回
§? Qt::AutoConnection:自動(dòng)連接(默認(rèn))意味著如果接受者所在線程就是當(dāng)前線程,則使用直接連接;否則將使用隊(duì)列連接
?
?
運(yùn)用線程容易踩的坑:
1、線程及線程管理者都存在依附性,線程管理者(Thread對(duì)象)依附于創(chuàng)建它(創(chuàng)建對(duì)象)的線程。所以例如,子線程類中存在槽函數(shù),主線程創(chuàng)建線程管理者對(duì)象及發(fā)出信號(hào)。連接
槽函數(shù)和信號(hào)后執(zhí)行發(fā)現(xiàn),本槽采用隊(duì)列連接,信號(hào)在主線程中發(fā)送,接收者槽函數(shù)也在主線程中。即本例槽函數(shù)實(shí)際上在主線程中執(zhí)行,如本槽運(yùn)行耗時(shí)操作,將阻塞主線程。
?
2、使用moveToThread可改變線程依附性,如上例中槽函數(shù)實(shí)際運(yùn)行在主函數(shù)中,此時(shí)使用moveToThread(線程管理者);講線程依附性移至子線程中,再執(zhí)行耗時(shí)操作講不會(huì)阻塞主線程。注意:子線程類想要接受信號(hào)必須在run()中寫exec();開啟子線程,否則連接信號(hào)槽將無效。
