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,并且解锁互斥量

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值