商會(huì)網(wǎng)站建設(shè)seo優(yōu)化網(wǎng)絡(luò)公司排名
文章目錄
- 一、主線程阻塞等待子線程返回
- 1、代碼示例
- 2、代碼改進(jìn)
一、主線程阻塞等待子線程返回
主線程等待一個(gè)線程,此線程會(huì)開始連接一個(gè)服務(wù)器并循環(huán)讀取服務(wù)器存儲(chǔ)的值,主線程會(huì)阻塞直到連接服務(wù)器成功。因?yàn)槿绻蛔枞?#xff0c;可能上層業(yè)務(wù)剛開始讀不到數(shù)據(jù)。
1、代碼示例
bool bConnect = false; // 退出條件void connectAndReadFromServer()
{// 模擬等待2秒連接服務(wù)器成功Sleep(2000);bConnect = true;// 模擬一個(gè)無(wú)限循環(huán)讀取服務(wù)器數(shù)據(jù)while (true){qDebug() << "I am working";Sleep(1000);}
}int main(int argc, char *argv[])
{std::thread t(connectAndReadFromServer);// 阻塞等待子線程返回,該方式在debug下運(yùn)行ok,release下不會(huì)阻塞。while (!bConnect){}qDebug() << "main thread continue, start read " << bConnect;return 0;
}
坑點(diǎn):上述代碼在debug下運(yùn)行是沒有問(wèn)題的,因?yàn)榫幾g器會(huì)關(guān)閉大部分優(yōu)化,目的是保留代碼的原始行為,方便調(diào)試。 但是在release模式下,編譯器發(fā)現(xiàn)該循環(huán)內(nèi)部無(wú)任何操作,會(huì)采取循環(huán)消除優(yōu)化,直接跳過(guò),主線程繼續(xù)執(zhí)行,所以此時(shí)bConnect為false。
2、代碼改進(jìn)
int num = 0;
while (!bConnect)
{Sleep(0); // ok 正常阻塞//空函數(shù)(); // no 直接優(yōu)化去掉//num++; // no bConnect條件拿不到
}
- Sleep(0) :主動(dòng)放棄CPU時(shí)間片,重新線程調(diào)度,還可以刷新主線程的寄存器和緩存,讓線程重新從內(nèi)存中讀取變量的最新值。
- 空函數(shù)() :在release下,該循環(huán)不執(zhí)行,直接被編譯器優(yōu)化掉。
- 變量++:就算連接成功,編譯器也會(huì)在release下優(yōu)化,bConnect條件變量的值被緩存到寄存器中(因?yàn)橐罅垦h(huán)讀),導(dǎo)致主線程無(wú)法感知到變量的變化。循環(huán)一直執(zhí)行。所以可以給變量num加
volatile關(guān)鍵字
,這樣也是可以正常阻塞的,通知編譯器不要優(yōu)化該變量,每次都從內(nèi)存中讀取最新的值。