c++11線程間參數傳遞


傳遞臨時對象作為線程參數

創建的工作線程不止一個,線程根據編號來確定工作內容。每個線程都需要知道自己的編號。線程中有很多容易犯錯的寫法

例子1

多線程需要執行的函數:

void  my_print( const  int  &i,  char * p_mybuff)
{
     cout << i << endl;
     cout << p_mybuff << endl;
     return  ;
}

 主函數的寫法

int  mvar = 1;
int & mvary = mvar;
char  mybuf[] =  "this is a test!" ;
thread  myobj(my_print, mvar, mybuf);
myobj.join();
 
cout <<  "Main Thread!!!"  << endl;

 解釋:注意陷阱!!!引用和指針的變量傳參。

引用:表面看起來似乎正確,但是細節上有很多地方需要注意的,如果把join()改成detach(),然后主線程和子線程分別執行,那么可能出現主線程執行完了,但是傳遞進去的參數(引用形式)的資源已經被釋放了,有沒有可能出現錯誤?:

myobj.detach()

  在創建thread對象的時候,做了一個復制,把值復制進去了,所以不是一個真引用,實際是值傳遞,不會出現資源釋放的錯誤。但是反過來想,那么主線程的變量的值並不會改變。

指針:如果傳遞的參數是指針,第二個參數不安全,如果用detach()執行線程的時候,不推薦用“引用”,指針絕對會有問題!

正確的用法是什么樣:不傳引用,如果要傳字符串的情況。

char* p_mybuff 改成 const string &p_mybuff ,確實不指向於同一塊內存,什么時候出現了變量類型的轉換?事實上存在主函數執行完了,p_mybuff 都被回收了,系統才用p_mybuff 去轉換string

thread  myobj(my_print, mvar, string(mybuf));

  如果用一個string 去強制類型轉換,生成一個臨時對象,此時的臨時對象會綁定到p_mybuff上。在創建線程的時候,構造臨時變量的方法傳遞參數是可行的,此時也會調用一次構造函數,此時detach也能正確運行。為了防止主線程退出,子線程內存的非法引用。

1) 對傳遞int,直接用值傳遞。

2) 如果傳遞類對象,避免隱式類型轉換。全部都在創建線程的時候就構建出臨時對象,在函數參數里用引用來接收傳遞的函數。否則系統還會多構造一次函數,造成不必要的浪費。

3) 主線程中類型轉換,那么A(mysecondpar) 這一步由主線程操作

thread myobj(myprint, mvar, A(mysecondpar));

thread myobj(myprint, mvar, mysecondpar);

4) 建議不使用detach,用join

傳遞臨時對象作為線程參數

線程ID:在操作系統的層面需要調度線程,有一個線程ID,以及線程ID的文件描述符,用來管理這個線程的資源分配。在線程之間需要調度,所以也有優先級的概念。每個線程對應一個ID,線程ID可以用C++標准庫里面的函數來獲取 std::this_thread::get_id()。

傳參函數給線程的時候,參數入口都是const,在函數中const不能修改,如果需要修改變量,就在初始化的時候“mutable”。在C++中,mutable也是為了突破const的限制而設置的。被mutable修飾的變量,將永遠處於可變的狀態,但是在多線程里面也有問題,如果真的要修改值,那么就使用std:ref(),這個ref和在C#里面是類似的,將方法內的變量改變后帶出方法外,用std:ref(),真正地把變量傳進去。

 完整的代碼:

#include "pch.h"
#include <iostream>
#include <thread>
 
using  namespace  std;
 
class  person {
public :
     int  m_age;
     person( int  a) :m_age(a) {
         cout <<  "person 的構造函數,進程為:"  << std::this_thread::get_id()<<endl;
     }
     person( const  person &p) :m_age(p.m_age) {
         cout <<  "person 的復制構造函數 "  << std::this_thread::get_id() << endl;
     }
     ~person() {
         cout <<  "person的析構函數 "  << std::this_thread::get_id() << endl;
     }
 
};
void  myprin( const  int  &num,  char  *p[]) {
     cout <<  "現在的線程是: "  << std::this_thread::get_id() << endl;
     cout <<  "傳入的參數是:"  << endl;
     cout << num <<  "  "  << p << endl;
}
void  print_class(person p)
{
     cout <<  "現在的線程是: "  << std::this_thread::get_id() << endl;
     cout <<  "print class: "  << p.m_age << endl;
}
 
int  main()
{
 
     std::cout <<  "主線程: " << std::this_thread::get_id()<<endl; 
     
     int  num = 1;
     //person student(num);
     thread  obj(print_class, person(10));
     
 
}

  

傳遞成員函數到線程中

將類的成員函數傳遞到線程中。

std:: thread  myobj(&classA::method, para1, para2,..);
myobj.join();

  

 

classA::method就是一個函數。


免責聲明!

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



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