C++ 多執行緒pthread 學習筆記
阿新 • • 發佈:2018-11-09
本篇是我在學習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,並且解鎖互斥量