c++多線程初步學習

c++多線程學習

學習資料來源於C++多線程菜鳥教程:c++多線程

本人使用環境 manjaro  ide爲vscode  c++11,

這裏需要注意,對於線程相關代碼編譯時需加入 -lpthread 即 g++ a.cpp -plthread

否則會顯示undefined reference to `pthread_create'

我這裏使用爲vscode按照剛開始配置文件無法通過vsc直接編譯,但是可以修改tasks.json文件

在args裏面加入 "-lpthread"即可  以下給我我的配置文件 修改後可直接編譯運行

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Compile", // 任務名稱,與launch.json的preLaunchTask相對應
            "command": "clang++", // 要使用的編譯器
            "args": [
                "${file}",
                "-o", // 指定輸出文件名,不加該參數則默認輸出a.exe,Linux下默認a.out
                "${fileDirname}/${fileBasenameNoExtension}.exe",
                "-g", // 生成和調試有關的信息
                "-Wall", // 開啓額外警告
                "-static-libgcc", // 靜態鏈接
                "-lpthread",
                "-fcolor-diagnostics", // 彩色的錯誤信息?但貌似clang默認開啓而gcc不接受此參數
                "-std=c++11" // C語言最新標準爲c11,或根據自己的需要進行修改
            ], // 編譯命令參數
            "type": "shell", // 可以爲shell或process,前者相當於先打開shell再輸入命令,後者是直接運行命令
            "group": {
                "kind": "build",
                "isDefault": true // 設爲false可做到一個tasks.json配置多個編譯指令,需要自己修改本文件,我這裏不多提
            },
            "presentation": {
                "echo": true,
                "reveal": "always", // 在“終端”中顯示編譯信息的策略,可以爲always,silent,never。具體參見VSC的文檔
                "focus": false, // 設爲true後可以使執行task時焦點聚集在終端,但對編譯c和c++來說,設爲true沒有意義
                "panel": "shared" // 不同的文件的編譯信息共享一個終端面板
            }
            // "problemMatcher":"$gcc" // 如果你不使用clang,去掉前面的註釋符,並在上一條之後加個逗號。照着我的教程做的不需要改(也可以把這行刪去)
        }
    ]
}

接下開始學習多線程:

首先是線程的創建

pthread_create (thread, attr, start_routine, arg) 

該函數有4個參數,分別代表

thread 指向線程標識符指針。
attr 一個不透明的屬性對象,可以被用來設置線程屬性。您可以指定線程屬性對象,也可以使用默認值 NULL。
start_routine 線程運行函數起始地址,一旦線程被創建就會執行。
arg 運行函數的參數。它必須通過把引用作爲指針強制轉換爲 void 類型進行傳遞。如果沒有傳遞參數,則使用 NULL。

看起來可能不是很清楚,直接上代碼。

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn=5
void *PrintHello(void *threadid)
{  
   int tid = *((int*)threadid);// 對傳入的參數進行強制類型轉換,由無類型指針變爲整形數指針,然後再讀取
   cout << "Hello Runoob! 線程 ID, " << tid << endl;
   pthread_exit(NULL);
}
 
int main ()
{
   pthread_t threads[maxn];
   int indexes[maxn];// 用數組來保存i的值
   for(int i=0; i < NUM_THREADS; i++ )
   {      
      cout << "main() : 創建線程, " << i << endl;
      indexes[i] = i; //先保存i的值
      // 傳入的時候必須強制轉換爲void* 類型,即無類型指針        
      int rc = pthread_create(&threads[i], NULL,PrintHello,(void *)&(indexes[i]));
      if (rc)
      {
         cout << "Error:無法創建線程," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

可以看到4個參數中,第3個參數代表該線程需要完成的任務,而最後一個參數是將在線程開始函數的傳入的參數,那麼有個問題,如何給函數傳入多個參數呢,

#include <bits/stdc++.h>
using namespace std;
const int maxn=5;

struct thread_data//創建一個結構體 格式爲將傳入的參數
{
    int thread_id;
    char *message;
};
void *print(void *threadarg)//函數這裏傳入的仍未空指針
{ 
    thread_data *mydata;
    mydata=(thread_data*) threadarg;//通過強制類型轉換將參數列表提取出來
    cout<<"Thread ID: "<<mydata->thread_id<<endl;
    cout<<"Thread message: "<<mydata->message<<endl;
    pthread_exit(NULL);
}
int main()
{
    pthread_t tids[maxn];
    thread_data td[maxn];//輸入參數
    for(int i=0;i<5;i++)
    {
        cout<<"main() : create thread, "<<i<<endl;
        td[i].thread_id=i;
        td[i].message="makise kurisu";
        int rc=pthread_create(&tids[i],NULL,print,(void*)&td[i]);//參數強轉爲void*
        if(rc)
        {
            cout<<"error"<<endl;
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

可以看到 通過類型強轉實現了函數傳入多個參數的方法,目前我只學習了這一個寫法,不清楚有沒有其他的,日後在更,現在的目的只是單純的瞭解多線程的基礎操作和原理。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章