C++11多線程 創建多個線程、數據共享問題

目錄

1.創建和等待多個線程

2.數據共享問題分析

2.1 只讀數據

2.2 有讀有寫:

3.共享數據的保護案例代碼


1.創建和等待多個線程

a)多個線程執行順序是亂的,跟操作系統內部對線程的運行調度機制有關;

b)主線程等待所有子線程運行結束,最後主線程結束,推薦使用這種join的寫法,更容易寫出穩定的程序;

c)咱們把thread對象放入到容器裏管理,看起開像個thread對象數組,這對我們一次創建大量線程並對大量線程進行管理很方便。

#include<iostream>
#include<thread>
#include<string>
#include<vector>

using namespace std;

void myprint(int inum)
{
	cout <<"myprint線程開始執行了,線程編號=" << inum <<endl;
	//.....
	cout << "myprint線程結束執行了,線程編號=" << inum << endl;
}

int main()
{
	vector<thread> mythreads;
	//創建10個線程,線程入口函數統一使用myprint

	for (int i = 0; i < 10; i++)
	{
		mythreads.push_back(thread(myprint,i)); //創建10個線程,同時這10個線程已經開始執行
	}

	for (auto iter = mythreads.begin(); iter!= mythreads.end(); iter++)
	{
		iter->join();  //等待10個線程都返回
	}

	cout << "主線程執行!" << endl;

	return 0;
}

2.數據共享問題分析

2.1 只讀數據

是安全穩定的,不需要特別的處理手段;直接讀就可以。

2.2 有讀有寫:

例如:2個線程寫,8個線程度,如果代碼沒有特別的處理,程序肯定崩潰!最簡單的不崩潰處理,讀的時候不能寫,寫的時候不能讀;兩個線程不能同時寫,八個線程不能同時讀。

讀寫都是分幾個小步完成的,由於切換,導致各種詭異的事情發生,如崩潰!

3.共享數據的保護案例代碼

網絡遊戲服務器。兩個自己創建的線程,一個線程收集玩家命令(一個數字代表玩家發來的命令),並把命令寫到一個隊列中;另外一個線程從隊列中取出玩家送來的命令,解析,然後執行玩家需要的動作;

list:頻繁的按順序插入和刪除數據時效率高。vector容器隨機的插入刪除數據效率高!

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>

using namespace std;

//準備用成員函數作爲線程函數的方法寫線程
class A
{
public:
	//把收到的消息入到一個隊列的線程
	void inMsgRecvQueue() 
	{
		for (int i = 0; i < 10000;i++)
		{
			cout << "inMsgRecvQueue()執行,插入一個元素"<< i<<endl;
			msgRecvQueue.push_back(i); //假設這個數字i就是收到的命令,直接弄到消息隊列裏邊來;
		}
	}

	//把數據從消息隊列取出的線程
	void outMsgRecvQueue()
	{
		for (int i = 0; i < 10000; i++)
		{
			if (!msgRecvQueue.empty())
			{
				//消息不爲空
				int command = msgRecvQueue.front();//返回第一個元素,但不檢查元素是否存在
				msgRecvQueue.pop_front();//移除第一個元素。但不返回;
				//這裏就考慮處理數據
			}
			else
			{
				//消息隊列爲空
				cout << "inMsgRecvQueue()執行,但目前消息隊列中爲空!" << i << endl;
			}
		}
		cout <<"end!" << endl;
	}

private:
	std::list<int> msgRecvQueue;//容器(消息隊列),代表玩家發送過來的命令。
};

int main()
{
	A myobja;

	std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobja);//第二個參數,引用,才能保證線程裏用的是同一個對象
	std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);

	myOutMsgObj.join();
	myInMsgObj.join();

	cout << "主線程執行!" << endl;

	return 0;
}

運行此程序,會報錯!

解決問題:引入一個C++解決多線程保護共享數據問題的第一個概念“互斥量”,下節介紹!

注:該文是C++11併發多線程視頻教程筆記,詳情學習:https://study.163.com/course/courseMain.htm?courseId=1006067356

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