1. 程式人生 > >建立多個執行緒、資料共享問題

建立多個執行緒、資料共享問題

目錄

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