天天看點

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");
}      

輸出:

C++使用thread類多線程程式設計

兩個子線程并行執行,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");
}      

輸出:

C++使用thread類多線程程式設計

使用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");
}      

輸出跟上例輸出一樣:

C++使用thread類多線程程式設計

多線程資料競争

多個線程同時對同一變量進行操作的時候,如果不對變量做一些保護處理,有可能導緻處理結果異常:

#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");
}      

輸出結果(部分):

C++使用thread類多線程程式設計

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

這是由于第一個線程對變量操作的過程中,第二個線程也對同一個變量進行各操作,導緻第一個線程處理完後的輸出有可能是線程二操作的結果。針對這種資料競争的情況,可以使用線程互斥對象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");
}