C++併發與多線程學習筆記--參數傳遞詳解

  • 傳遞臨時對象
    • 陷阱
    • 總結
  • 臨時對象做爲線程參數
    • 線程id的概念
    • 臨時對象構造時的抓捕
  • 成員函數指針作線程函數

傳遞臨時對象做爲線程參數

建立的工做線程不止一個,線程根據編號來肯定工做內容。每一個線程都須要知道本身的編號。線程中有不少容易犯錯的寫法ios

例子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;

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

引用:表面看起來彷佛正確,可是細節上有不少地方須要注意的,若是把join()改爲detach(),而後主線程和子線程分別執行,那麼可能出現主線程執行完了,可是傳遞進去的參數(引用形式)的資源已經被釋放了,有沒有可能出現錯誤?:spa

myobj.detach()

  在建立thread對象的時候,作了一個複製,把值複製進去了,因此不是一個真引用,實際是值傳遞,不會出現資源釋放的錯誤。可是反過來想,那麼主線程的變量的值並不會改變。操作系統

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

正確的用法是什麼樣:不傳引用,若是要傳字符串的狀況。指針

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

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就是一個函數。
相關文章
相關標籤/搜索