解析 QT 多線程程序之可重入與線程安全 中篇
QT 多線程程序之可重入與線程安全 是本節(jié)要介紹的內(nèi)容,繼續(xù)著 解析 QT 多線程程序詳細(xì)設(shè)計 上篇 ,開始介紹。先來看內(nèi)容。
在Qt文檔中,術(shù)語“可重入”與“線程安全”被用來說明一個函數(shù)如何用于多線程程序。假如一個類的任何函數(shù)在此類的多個不同的實(shí)例上,可以被多個線程同時調(diào)用,那么這個類被稱為是“可重入”的。假如不同的線程作用在同一個實(shí)例上仍可以正常工作,那么稱之為“線程安全”的。
大多數(shù)c++類天生就是可重入的,因為它們典型地僅僅引用成員數(shù)據(jù)。任何線程可以在類的一個實(shí)例上調(diào)用這樣的成員函數(shù),只要沒有別的線程在同一個實(shí)例上調(diào)用這個成員函數(shù)。舉例來講,下面的Counter 類是可重入的:
- class Counter{public: Counter() {
- n=0;
- }
- void increment() {
- ++n;
- }
- void decrement() {
- --n;
- }
- int value() const {
- return n;
- }private: int n;
- };
這個類不是線程安全的,因為假如多個線程都試圖修改數(shù)據(jù)成員 n,結(jié)果未定義。這是因為c++中的++和--操作符不是原子操作。實(shí)際上,它們會被擴(kuò)展為三個機(jī)器指令:
1,把變量值裝入寄存器
2,增加或減少寄存器中的值
3,把寄存器中的值寫回內(nèi)存
假如線程A與B同時裝載變量的舊值,在寄存器中增值,回寫。他們寫操作重疊了,導(dǎo)致變量值僅增加了一次。很明顯,訪問應(yīng)該串行化:A執(zhí)行123步驟時不應(yīng)被打斷。使這個類成為線程安全的最簡單方法是使用QMutex來保護(hù)數(shù)據(jù)成員:
- class Counter{public: Counter() {
- n = 0;
- }
- void increment() {
- QMutexLocker locker(&mutex); ++n;
- }
- void decrement() {
- QMutexLocker locker(&mutex);
- --n;
- }
- int value() const {
- QMutexLocker locker(&mutex);
- return n;
- }private: mutable QMutex mutex;
- int n;
- };
QMutexLocker類在構(gòu)造函數(shù)中自動對mutex進(jìn)行加鎖,在析構(gòu)函數(shù)中進(jìn)行解鎖。隨便一提的是,mutex使用了mutable關(guān)鍵字來修飾,因為我們在value()函數(shù)中對mutex進(jìn)行加鎖與解鎖操作,而value()是一個const函數(shù)。
大多數(shù)Qt類是可重入,非線程安全的。有一些類與函數(shù)是線程安全的,它們主要是線程相關(guān)的類,如QMutex,QCoreApplication::postEvent()。
線程與QObjects
QThread 繼承自QObject,它發(fā)射信號以指示線程執(zhí)行開始與結(jié)束,而且也提供了許多slots。更有趣的是,QObjects可以用于多線程,這是因為每個線程被允許有它自己的事件循環(huán)。
小結(jié):QT 多線程程序之可重入與線程安全的內(nèi)容介紹完了,希望本文能夠?qū)δ阌兴鶐椭?,如果你對本文感興趣或者需要獲得更多的資料,請參考






















