多任務(wù)編程超入門-關(guān)于mutex,你必須知道的
前一篇文章講了一個故事,本文換一種方式繼續(xù)說明。如果將兩篇文章結(jié)合起來看,相信會更有趣。
這部分內(nèi)容看起來簡單,但卻是經(jīng)常出錯的地方。
面臨的問題
多線程同時操作一段數(shù)據(jù)時,線程調(diào)度由操作系統(tǒng)控制,在機器碼層次進(jìn)行,所以訪問同一數(shù)據(jù)的多個任務(wù)(線程)的代碼隨機交替執(zhí)行,從而導(dǎo)致任務(wù)(線程)間數(shù)據(jù)交換不能正常進(jìn)行。
解決問題的方式
問題搞清楚以后,對策當(dāng)然就是保證每個線程內(nèi)操作數(shù)據(jù)的處理的完整性。但是C/C++中達(dá)成這個目標(biāo)的手段不是將數(shù)據(jù)保護(hù)起來,而是限制操作數(shù)據(jù)的代碼的同時執(zhí)行。具體說,就是在開始執(zhí)行操作數(shù)據(jù)的代碼之前先通過mutex::lock方法鎖定互斥量,然后執(zhí)行對數(shù)據(jù)進(jìn)行操作的代碼。數(shù)據(jù)操作代碼執(zhí)行完了之后,再通過mutex::unlock釋放互斥量。在互斥量的鎖定期間其他線程無法鎖定信號量。
由于操作系統(tǒng)可以保證同一時刻只有一個線程可以鎖定成功,所以只要程序在所有操作同一數(shù)據(jù)的代碼之前都有鎖定互斥量的動作,結(jié)果上就可以保證同一時刻只有一段操作數(shù)據(jù)的代碼可以執(zhí)行,而不被其他操作改數(shù)據(jù)的代碼打斷。這樣就間接保證了數(shù)據(jù)的完整性。
注意事項
根據(jù)上面的描述,可以知道,使用Mutex進(jìn)行數(shù)據(jù)交互必須遵循以下原則:
所有操作數(shù)據(jù)的代碼在執(zhí)行之前必須首先嘗試鎖定同一個互斥量
只有在互斥量鎖定成功的情況下才允許執(zhí)行操作數(shù)據(jù)的代碼
操作數(shù)據(jù)的代碼執(zhí)行以后,必須釋放互斥量
如果在操作數(shù)據(jù)之前沒有鎖定互斥量的過程,或者鎖定的是不同的互斥量,無論哪一種情況都達(dá)成不了同一時刻,只有一段代碼執(zhí)行的目標(biāo)。
如果操作數(shù)據(jù)的代碼執(zhí)行之后沒有釋放互斥量,后續(xù)處理數(shù)據(jù)的代碼將永遠(yuǎn)不能鎖定互斥量,也就是說,后續(xù)的數(shù)據(jù)處理不能繼續(xù)執(zhí)行。
請按照上述原則在審視一下代碼,主要關(guān)注mutex:
QMutex?mutex;???? //define?CreateDataTask?class. class?CreateDataTask?:?public?QThread { public: ????CreateDataTask(QMutex&?mutex) ????????:m_mutex(mutex) ???{ ???} private: ????QMutex&?m_mutex; ????void?() ????{ ????????for(int?i?=?0;?i?<?10;?++i) ????????{ ????????????m_mutex.lock(); ????????????cout?<<?"WT:<<<<WriteData:"?<<?i??? ?????????????????????????????<<?"<<<<"?<<?endl; ????????????WriteData(); ????????????m_mutex.unlock(); ????????} ????} }; ::timeBeginPeriod(1); //Create?thread?object?of?CreateDataTask. CreateDataTask?*writer?=? ?????????????????new?CreateDataTask(mutex); //Start?Thread. writer->start(QThread::NormalPriority); for(int?i?=?0;?i?<?10;?++i) { ????mutex.lock(); ????cout?<<?"RT:>>>>ReadData:"?<<?i? ???????????????????????<<?">>>>"?<<?endl; ????ReadData(); ????data_array.clearData(); ????mutex.unlock(); } timeEndPeriod(1);
應(yīng)該講點原則
有一種說法,飛機是試飛員飛出來的,估計也會有很多人說,程序是程序員Debug出來的。這種觀點作者實在是不敢茍同。多任務(wù)編程就是一個不能靠調(diào)試解決問題的例子。必須遵循上面的原則,否則的話程序的動作會有很大的不確定性。在開發(fā)的最后階段,多任務(wù)相關(guān)的問題都會占有相當(dāng)大的比例。那簡直就是程序員的噩夢。
必須講點原則。