C++11多線程編程(常見面試題)


【題目1】

子線程循環 10 次,接着主線程循環 100 次,接着又回到子線程循環 10 次,接着再回到主線程又循環 100 次,如此循環50次,試寫出代碼

 

【題解】

首先我們來分析一下這道題...(是個剛入門的小白,分析的不好請見諒)

1、由於子線程需要循環10次不受主線程干擾,而主線程需要循環100次不受子線程干擾,所以顯然,在他們進入循環的時候需要一個鎖把這段循環鎖住,不然會導致資源被搶占(此處的資源可以理解為是循環里的cout)。(其實簡單來說互斥量是為了保證子線程和主線程的for不同時進行

2、然后問題來了,怎么控制子線程循環后主線程循環,然后一直這樣依次循環呢?條件變量就可以做到這點,我們可以通過改變某個全局變量的值,第一次將該全局變量置為10,也就是說我們只要控制如果傳入的參數和該全局變量不等,就讓他一直等待,當執行完子線程的循環后改變這個全局變量為100,那么對於子線程來說全局變量和傳入的參數就不相等了,那么條件變量就會一直等待。當然如果一直讓他等待肯定是不對的,所以當一個線程執行完循環之后需要喚醒這個條件變量,告訴線程變量已經改變又可以開始搶資源啦。(其實條件變量就是為了控制子主線程運行的先后條件

 

【代碼】

#include<thread>
#include<iostream>
#include<cstdio>
#include<mutex>
#include<condition_variable>
using namespace std;
int flag = 10;
mutex mu;
condition_variable cv;
void fun(int x, char c)
{
    for (int i = 0; i < 50; i++)
    {
        unique_lock<mutex> lock(mu);
        while(flag != x)
            cv.wait(lock);//在該線程阻塞之前會執行lock.unlock,這樣別的線程才不會被鎖住
        for (int j = 0; j < x; j++)
            cout << c << ":" << j << endl;
        flag = (x == 10)? 100 : 10;
        cv.notify_one();
    }
}
int main()
{
    thread t1(fun, 10, 'A');
    fun(100, 'B');
    t1.join();
}
View Code

 

【總結】

理解這段代碼的時候,被wait()弄了好久,可能是我太蠢qwq那么來說一下wait()吧,我們分兩種情況來說。

(1)一開始,主線程先搶到了鎖

那么就會判斷flag是否等於x,很顯然如果是主線程先拿到鎖此時flag=10,x=100不等,那么這個時候主線程就會執行wait(),也就是會被阻塞,然后因為wait()自身有這樣一個機制(當他執行的時候會自動釋放鎖嗎,也就是會自動執行unlock,給其他線程一個拿鎖的機會),這個時候子線程就會拿到鎖,並且判斷fag是否等於x,這時候明顯是相等的,那么就會進行下面的一系列循環,這個時候重點來了,一定要改變全局變量!!如果不改變會是什么結果呢?假設我們把那句話注釋掉直接執行notify_one(),那么主線程就會被喚醒它的wait()又會自動參與搶鎖,由於flag沒有改變,那么flag和x的值還是相等,所以它依然會被阻塞,那么依舊就是子線程執行,就不滿足題意了。

(2)一開始,子線程先搶到了鎖

因為滿足flag=x,那么會執行接下來的for,按部就班改個flag,然后喚醒被wait的線程(這時候其實沒有),因為執行完一個循環,uniqie_lock會自動釋放鎖,然后子線程和主線程就又開始搶鎖了,這次我們假設還是子線程先搶到了鎖,但由於修改了flag,此時flag!=x,子線程就被阻塞,然后就和情況(1)差不多啦。

 

 

【題目2】

編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推。

 

【題解】

其實只要理解了上一題,就是一個套路啦。這里有所不同的是有3個線程,所以最后喚醒條件變量的時候記得用notify_all()。

 

【代碼】

#include<thread>
#include<iostream>
#include<cstdio>
#include<mutex>
#include<condition_variable>
using namespace std;
int flag = 0;
mutex mu;
condition_variable cv;
void fun(int x)
{
    for (int i = 0; i < 10; i++)
    {
        unique_lock<mutex>lock(mu);
        while (x != flag)
            cv.wait(lock);
        cout << static_cast<char>('A' + x) << " ";
        flag = (flag + 1) % 3;
        cv.notify_all();
    }
}
int main()
{
    thread t1(fun, 1);
    thread t2(fun, 2);
    fun(0);
    t1.join();
    t2.join();
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM