NDK14_C++基礎:C++線程

NDK開發彙總

線程,有時被稱爲輕量進程,是程序執行的最小單元。

C++11線程

#include <thread>

void task(int i) {
	cout << "task:" << i << endl;
}

thread t1(task,100);
//等待線程結束再繼續執行
t1.join();

POSIX線程

POSIX 可移植操作系統接口,標準定義了操作系統應該爲應用程序提供的接口標準

Windows上使用 配置: 下載

cmake_minimum_required (VERSION 3.8)
include_directories("XXX/pthreads-w32-2-9-1-release/Pre-built.2/include")
#設置變量爲x64 or x86
if(CMAKE_CL_64)
    set(platform x64)
else()
    set(platform x86)
endif()
link_directories("XXX/pthreads-w32-2-9-1-release/Pre-built.2/lib/${platform}")
#如果出現 “timespec”:“struct” 類型重定義 設置
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_STRUCT_TIMESPEC")
# 將源添加到此項目的可執行文件。
add_executable (lsn6example "lsn6_example.cpp" "lsn6_example.h")
target_link_libraries(lsn6example pthreadVC2)

32位拷貝pthreadVC2.dll 到windows/syswow64目錄
64位拷貝pthreadVC2.dll 到windows/system32目錄

#include <pthread.h>
void *pthreadTask(void* args) {
	int* i = static_cast<int*>(args);
	cout << "posix線程:" << *i << endl;
	return 0;
}
pthread_t pid;
int pi = 100;
pthread_create(&pid, 0, pthreadTask, &pi);
//等待線程的結束
pthread_join(pid,0);

線程屬性

線程具有屬性,用 pthread_attr_t 表示

pthread_attr_t attr;
//初始化 attr中爲操作系統實現支持的線程所有屬性的默認值
pthread_attr_init(&attr);
pthread_attr_destroy(&attr);

分離線程

線程創建默認是非分離的,當pthread_join()函數返回時,創建的線程終止,釋放自己佔用的系統資源
分離線程不能被其他線程等待,pthread_join無效,線程自己玩自己的。

//設置是否爲分離線程
//PTHREAD_CREATE_DETACHED 分離
//PTHREAD_CREATE_JOINABLE 非分離
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

調度策略與優先級

Windows 無法設置成功

//設置調度策略 
//返回0 設置成功
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
// SCHED_FIFO 
//	實時調度策略,先到先服務 一旦佔用cpu則一直運行。一直運行直到有更高優先級任務到達或自己放棄。
// SCHED_RR
//	實時調度策略,時間輪轉 系統分配一個時間段,在時間段內執行本線程


//設置優先級
//獲得對應策略的最小、最大優先級
int max = sched_get_priority_max(SCHED_FIFO);
int min = sched_get_priority_min(SCHED_FIFO);
sched_param param;
param.sched_priority = max;
pthread_attr_setschedparam(&attr, &param);

線程同步

多線程同時讀寫同一份共享資源的時候,可能會引起衝突。需要引入線程“同步”機制,即各位線程之間有序地對共享資源進行操作。

#include <pthread.h>
using namespace std;

queue<int> q;
void *pop(void* args) {
    //線程未同步導致的多線程安全問題
    // 會有重複的數據取出並出現異常
	if (!q.empty())
	{
		printf("取出數據:%d\n", q.front());
		q.pop();
	}
	else {
		printf("無數據\n");
	}
	return 0;
}

int main()
{
	for (size_t i = 0; i < 5; i++)
	{
		q.push(i);
	}
	pthread_t pid[10];
	for (size_t i = 0; i < 10; i++)
	{
		pthread_create(&pid[i], 0, pop, &q);
	}
	system("pause");
	return 0;
}

加入互斥鎖

queue<int> q;
pthread_mutex_t mutex;
void *pop(void* args) {
	// 鎖
	pthread_mutex_lock(&mutex);
	if (!q.empty())
	{
		printf("取出數據:%d\n", q.front());
		q.pop();
	}
	else {
		printf("無數據\n");
	}
    // 放
	pthread_mutex_unlock(&mutex);
	return 0;
}

int main()
{
    //初始化互斥鎖
	pthread_mutex_init(&mutex, 0);
	for (size_t i = 0; i < 5; i++)
	{
		q.push(i);
	}
	pthread_t pid[10];
	for (size_t i = 0; i < 10; i++)
	{
		pthread_create(&pid[i], 0, pop, &q);
	}
    //需要釋放
 	for (size_t i = 0; i < 10; i++)
	{
		pthread_join(pid[i], 0);
	}
	pthread_mutex_destroy(&mutex);
	system("pause");
	return 0;
}

條件變量

條件變量是線程間進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變量的條件成立"而掛起;另一個線程使"條件成立",從而喚醒掛起線程


```cpp
template <class T>
class SafeQueue {
public:
	SafeQueue() {
		pthread_mutex_init(&mutex,0);
	}
	~SafeQueue() {
		pthread_mutex_destory(&mutex);
	}
	void enqueue(T t) {
		pthread_mutex_lock(&mutex);
		q.push(t);
		pthread_mutex_unlock(&mutex);
	}
	int dequeue(T& t) {
		pthread_mutex_lock(&mutex);
		if (!q.empty())
		{
			t = q.front();
			q.pop();
			pthread_mutex_unlock(&mutex);
			return 1;
		}
		pthread_mutex_unlock(&mutex);
		return 0;
	}

private:
	queue<T> q;
	pthread_mutex_t mutex;
};
> 上面的模板類存放數據T,並使用互斥鎖保證對queue的操作是線程安全的。這就是一個生產/消費模式。

> 如果在取出數據的時候,queue爲空,則一直等待,直到下一次enqueue加入數據。

> 這就是一個典型的生產/消費模式, 加入條件變量使 “dequeue” 掛起,直到由其他地方喚醒

```cpp
#pragma once
#include <queue>
using namespace std;

template <class T>
class SafeQueue {
public:
	SafeQueue() {
		pthread_mutex_init(&mutex,0);
		pthread_cond_init(&cond, 0);
	}
	~SafeQueue() {
		pthread_mutex_destory(&mutex);
		pthread_cond_destory(&cond);
	}
	void enqueue(T t) {
		pthread_mutex_lock(&mutex);
		q.push(t);
		//發出信號 通知掛起線程
		//由系統喚醒一個線程
		//pthread_cond_signal(&cond);
		// 廣播 對應多個消費者的時候 多個線程等待喚醒所有
		pthread_cond_broadcast(&cond);
		pthread_mutex_unlock(&mutex);
	}
	int dequeue(T& t) {
		pthread_mutex_lock(&mutex);
		//可能被意外喚醒 所以while循環
		while (q.empty())
		{
			pthread_cond_wait(&cond, &mutex);
		}
		t = q.front();
		q.pop();
		pthread_mutex_unlock(&mutex);
		return 1;
	}

private:
	queue<T> q;
	pthread_mutex_t mutex;
	pthread_cond_t cond;
};
#include "lsn6_example.h"
#include <thread>
#include <pthread.h>

using namespace std;
#include "safe_queue.h"

SafeQueue<int> q;

void *get(void* args) {
	while (1) {
		int i;
		q.dequeue(i);
		cout << "消費:"<< i << endl;
	}
	return 0;
}
void *put(void* args) {
	while (1)
	{
		int i;
		cin >> i;
		q.enqueue(i);
	}
	return 0;
}
int main()
{
	pthread_t pid1, pid2;
	pthread_create(&pid1, 0, get, &q);
	pthread_create(&pid2, 0, put, &q);
	pthread_join(pid2,0);
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章