1. 程式人生 > >C++ 多執行緒pthread 學習筆記

C++ 多執行緒pthread 學習筆記

本篇是我在學習C++多執行緒的時候做的筆記,主要記錄的是基礎的流程,部分程式碼例項,以及重點函式的說明。

pthread 入口函式型別說明

void * func1(void * t)

void* 表示無型別指標

void*作為函式引數,表示函式接收一個指標,不管是什麼型別的指標都可以,但是傳遞之前要強制轉換為無型別指標。

基礎流程

pthread_t t1;//宣告一個執行緒
pthread_create(&t1, NULL, &test, (void *)this);//建立一個執行緒
pthread_exit(NULL);//退出執行緒

pthread_create()



函式原型

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                            void *(*start_routine) (void *), void *arg);

含有四個引數,

  • 第一個引數表示執行緒id
  • 第二個引數表示執行緒引數
  • 第三個是執行緒的入口函式名字
  • 第四個引數表示執行緒入口函式的引數名字

pthread_exit();

函式原型

void  pthread_exit(void  *retval)

寫線上程內部,用於強制退出當前執行緒

如果執行緒是joinable,可以在函式引數裡面傳遞執行緒的退出資訊給主執行緒

例如

#include <pthread.h>
#include <iostream>

using namespace std;

void *thread1(void *);
int status;
int main(void)
{
	void *status_m;
	cout << "status_m addr is " << &status_m << endl;
	pthread_t t_a;
	pthread_create(&t_a,NULL,thread1,NULL);/*建立程序t_a*/
	pthread_join(t_a, &status_m);/*等待程序t_a結束*/
	cout << "status_m value is " << status_m << endl;
	int * re=(int *)status_m;
	cout << "the value is " << *re << endl;
	return 0;
}
void *thread1(void *junk)
{
    status=23333;
	cout << "status addr is " << &status << endl;
	pthread_exit((void *)&status);
}


可以打印出

status_m addr is 0x7ffe3cfd6170
status addr is 0x6021b4
status_m value is 0x6021b4
the value is 23333

執行緒的joinable和detached屬性

屬性的設定方法如下

pthread_attr_t attr;//宣告一個引數
pthread_attr_init(&attr);//對引數進行初始化
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);//設定執行緒為可連線的
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//設定執行緒為可分離的
pthread_attr_destroy(&attr)//銷燬屬性,防止記憶體洩漏

屬性的相關操作如下:

pthread_detach()

函式原型

int pthread_detach(pthread_t tid);

detached的執行緒在結束的時候會自動釋放執行緒所佔用的資源

pthread_join()

函式原型

int pthread_join(pthread_t tid, void **status);

joinable的執行緒必須用pthread_join()函式來釋放執行緒所佔用的資源,如果沒有執行這個函式,那麼執行緒的資源永遠得不到釋放。

互斥鎖 mutex

互斥鎖是為了多個執行緒在執行過程中保持資料同步引入的機制。

基本流程

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/
pthread_mutex_init(&mutex,NULL);/*動態初始化互斥鎖*/
pthread_mutex_lock(&mutex);//加鎖
pthread_mutex_unlock(&mutex);//解鎖
pthread_mutex_destroy(&mutex);//銷燬互斥鎖

舉個例子

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t mutex ;
void *print_msg(void *arg){
        int i=0;
        pthread_mutex_lock(&mutex);
        for(i=0;i<15;i++){
                printf("output : %d\n",i);
                usleep(100);
        }
        pthread_mutex_unlock(&mutex);
}
int main(int argc,char** argv){
        pthread_t id1;
        pthread_t id2;
        pthread_mutex_init(&mutex,NULL);
        pthread_create(&id1,NULL,print_msg,NULL);
        pthread_create(&id2,NULL,print_msg,NULL);
        pthread_join(id1,NULL);
        pthread_join(id2,NULL);
        pthread_mutex_destroy(&mutex);
        return 1;
}

條件變數

基本流程

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化條件變數*/
pthread_mutex_lock(&mutex);/*鎖住互斥量*/
pthread_cond_signal(&cond);//傳送訊號量 跟wait函式不在同一個執行緒中
pthread_cond_wait(&cond,&mutex);//阻塞執行緒,等待條件變數,同時解鎖互斥量
pthread_mutex_unlock(&mutex);//解鎖互斥量
pthread_mutex_destroy(&mutex);//銷燬互斥鎖
pthread_cond_destroy(&cond);//銷燬條件變數

舉個例子

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化條件變數*/

void *thread1(void *);
void *thread2(void *);

int i=1;

int main(void)
{
	pthread_t t_a;
	pthread_t t_b;
	pthread_create(&t_a,NULL,thread1,(void *)NULL);/*建立程序t_a*/
	pthread_create(&t_b,NULL,thread2,(void *)NULL); /*建立程序t_b*/
	pthread_join(t_a, NULL);/*等待程序t_a結束*/
	pthread_join(t_b, NULL);/*等待程序t_b結束*/
	pthread_mutex_destroy(&mutex);
	pthread_cond_destroy(&cond);
	exit(0);
}
void *thread1(void *junk)
{
	for(i=1;i<=6;i++)
	{
		printf("thread1: Line: %d, i = %d\n", __LINE__, i);
		pthread_mutex_lock(&mutex);/*鎖住互斥量*/
		printf("thread1: lock %d\n", __LINE__);
		if(i%3==0)
		{
			printf("thread1:signal 1 %d\n", __LINE__);
			pthread_cond_signal(&cond);/*條件改變,傳送訊號,通知t_b程序*/
			printf("thread1:signal 2 %d\n", __LINE__);
			printf("%s will sleep 1s in Line: %d \n", __FUNCTION__, __LINE__);
			sleep(1);
		}
		pthread_mutex_unlock(&mutex);/*解鎖互斥量*/
		printf("thread1: unlock %d\n", __LINE__);
		printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
		sleep(1);
	}
}


void *thread2(void *junk)
{
	while(i<6)
	{
		printf("thread2: Line: %d, i = %d\n", __LINE__, i);
		pthread_mutex_lock(&mutex);
		printf("thread2: lock %d\n", __LINE__);
		if(i%3!=0)
		{
			printf("thread2: wait 1 %d\n", __LINE__);
			pthread_cond_wait(&cond,&mutex);/*解鎖mutex,並等待cond改變*/
			printf("thread2: wait 2 %d\n", __LINE__);
		}
		pthread_mutex_unlock(&mutex);
		printf("thread2: unlock %d\n", __LINE__);
		printf("%s will sleep 1s in Line: %d \n\n", __FUNCTION__, __LINE__);
		sleep(1);
	}
}

結果為:

thread1: Line: 29, i = 1
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: Line: 52, i = 1
thread2: lock 54
thread2: wait 1 57
thread1: Line: 29, i = 2
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread1: Line: 29, i = 3
thread1: lock 31
thread1:signal 1 34
thread1:signal 2 36
thread1 will sleep 1s in Line: 37 
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: wait 2 59
thread2: unlock 62
thread2 will sleep 1s in Line: 63 

thread1: Line: 29, i = 4
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread2: Line: 52, i = 4
thread2: lock 54
thread2: wait 1 57
thread1: Line: 29, i = 5
thread1: lock 31
thread1: unlock 41
thread1 will sleep 1s in Line: 42 

thread1: Line: 29, i = 6
thread1: lock 31
thread1:signal 1 34
thread1:signal 2 36
thread1 will sleep 1s in Line: 37 
thread1: unlock 41
thread2: wait 2 59
thread2: unlock 62
thread2 will sleep 1s in Line: 63 

thread1 will sleep 1s in Line: 42 

注意:thread2 wait 1和thread2 wait 2的位置可以知道wait函式在執行的時候會阻塞thread2,並且解鎖互斥量