1. 程式人生 > >C++使用thread類進行多執行緒程式設計

C++使用thread類進行多執行緒程式設計

C++11中引入了一個用於多執行緒操作的thread類,簡單多執行緒示例:

#include <iostream>
#include <thread>
#include <Windows.h>
 
using namespace std;
 
void thread01()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 01 is working !" << endl;
        Sleep(100);
    }
}
void thread02()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 02 is working !" << endl;
        Sleep(200);
    }
}
 
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.join();
    task02.join();
 
    for (int i = 0; i < 5; i++)
    {
        cout << "Main thread is working !" << endl;
        Sleep(200);
    }
    system("pause");
}

輸出:

兩個子執行緒並行執行,join函式會阻塞主流程,所以子執行緒都執行完成之後才繼續執行主執行緒。可以使用detach將子執行緒從主流程中分離,獨立執行,不會阻塞主執行緒:

#include <iostream>
#include <thread>
#include <Windows.h>
 
using namespace std;
 
void thread01()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 01 is working !" << endl;
        Sleep(100);
    }
}
void thread02()
{
    for (int i = 0; i < 5; i++)
    {
        cout << "Thread 02 is working !" << endl;
        Sleep(200);
    }
}
 
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.detach();
    task02.detach();
 
    for (int i = 0; i < 5; i++)
    {
        cout << "Main thread is working !" << endl;
        Sleep(200);
    }
    system("pause");
}

輸出:

使用detach的主執行緒和兩個子執行緒並行執行。

帶參子執行緒

在繫結的時候也可以同時給帶引數的執行緒傳入引數:

#include <iostream>
#include <thread>
#include <Windows.h>
 
using namespace std;
 
//定義帶引數子執行緒
void thread01(int num)
{
    for (int i = 0; i < num; i++)
    {
        cout << "Thread 01 is working !" << endl;
        Sleep(100);
    }
}
void thread02(int num)
{
    for (int i = 0; i < num; i++)
    {
        cout << "Thread 02 is working !" << endl;
        Sleep(200);
    }
}
 
int main()
{
    thread task01(thread01, 5);  //帶引數子執行緒
    thread task02(thread02, 5);
    task01.detach();
    task02.detach();
 
    for (int i = 0; i < 5; i++)
    {
        cout << "Main thread is working !" << endl;
        Sleep(200);
    }
    system("pause");
}

輸出跟上例輸出一樣:

多執行緒資料競爭

多個執行緒同時對同一變數進行操作的時候,如果不對變數做一些保護處理,有可能導致處理結果異常:

#include <iostream>
#include <thread>
#include <Windows.h>
 
using namespace std;
 
int totalNum = 100;
 
void thread01()
{
    while (totalNum > 0)
    {
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
    }
}
void thread02()
{
    while (totalNum > 0)
    {
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
    }
}
 
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.detach();
    task02.detach();
    system("pause");
}

輸出結果(部分):

有兩個問題,一是有很多變數被重複輸出了,而有的變數沒有被輸出;二是正常情況下每個執行緒輸出的資料後應該緊跟一個換行符,但這裡大部分卻是另一個執行緒的輸出。

這是由於第一個執行緒對變數操作的過程中,第二個執行緒也對同一個變數進行各操作,導致第一個執行緒處理完後的輸出有可能是執行緒二操作的結果。

針對這種資料競爭的情況,可以使用執行緒互斥物件mutex保持資料同步。

mutex類的使用需要包含標頭檔案mutex:

#include <iostream>
#include <thread>
#include <Windows.h>
#include <mutex>
 
using namespace std;
 
mutex mu;  //執行緒互斥物件
 
int totalNum = 100;
 
void thread01()
{
    while (totalNum > 0)
    {
        mu.lock(); //同步資料鎖
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
        mu.unlock();  //解除鎖定
    }
}
void thread02()
{
    while (totalNum > 0)
    {
        mu.lock();
        cout << totalNum << endl;
        totalNum--;
        Sleep(100);
        mu.unlock();
    }
}
 
int main()
{
    thread task01(thread01);
    thread task02(thread02);
    task01.detach();
    task02.detach();
    system("pause");
}

多執行緒中加入mutex互斥物件之後輸出正常:

後記:

C++11之前,Windows系統為我們提供了相關API,我們可以使用他們來進行多執行緒程式設計

C++11 thead 多執行緒類