4月「掘金·日新计划」第9天
一、相关函数
进程函数包含3点:线程,互斥锁,条件
二、实践使用
pthread库,编译-pthread
2.1、线程pthread_create,pthread_exit,pthread_join,pthread_self,pthread_equal
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
功能:创建线程
参数:
- pthread_t指针t1
- 线程属性,NULL
- 函数指针,线程执行的函数
- 传递数据,无类型数据(可以传结构体数据)
返回值:成功0,错误错误编号
void pthread_exit(void *retval);
功能:退出线程
参数:无类型指针,线程退出传的数据,要保证内存不释放,static关键字
int pthread_join(pthread_t thread, void **retval);
功能:等待,主函数阻塞等待线程退出
参数:
- t1
- 退出返回值,二级指针,就是退出函数的参数
pthread_t pthread_self(void);
功能:返回线程id
返回值:长整形,%ld
int pthread_equal(pthread_t t1, pthread_t t2);
功能:id比较
返回值:相等非0,否则0
例子:
- 创建线程
- 编写线程函数,输出主函数的值(结构体指针数组)和线程id,退出返回一个数据
- 主函数,输出id,等待线程,输出线程退出的数
- 注:编译加-lpthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct Student{
int arg;
char name[12];
struct Student *next;
}student;
//线程执行函数
void *fun1(void *ar)
{
static char *ptr = "wei"; //返回数据,要static防止释放
student **p = (student **)ar; //要用二级指针,因为数组里面还是地址
printf("t1:arg1=%d\n",p[0]->arg); //打印,结构体里的内容
// student *p = *(student **)ar;
// printf("t1:arg1=%d\n", p->arg);
printf("t1:name1=%s\n",p[0]->name);
printf("t1:arg2=%d\n",p[1]->arg);
printf("t1:name2=%s\n",p[1]->name);
printf("t1:id=%ld\n",(unsigned long)pthread_self()); //打印id
pthread_exit((void *)ptr); //退出线程,返回ptr数据
}
int main()
{
pthread_t t1;
student s1={21,"xiao"}; //定义2个结构体变量
student s2={30,"wei"};
student *array[2]={&s1, &s2}; //放入结构体指针数组
int arg = 100; //
char *a = NULL; //线程退出,数据接收指针
if(pthread_create(&t1, NULL, fun1, (void *)array) == 0){ //创建线程,传入指针数组
printf("found thread succeed\n");
}
printf("main:id=%ld\n",(unsigned long)pthread_self()); //打印id
pthread_join(t1, (void **)&a); //等待线程退出,阻塞
printf("main:t1 exit,%s\n",(char*)a); //打印线程退出返回的数据
return 0;
}
/*
found thread succeed
main:id=139959759869760
t1:arg1=21
t1:name1=xiao
t1:arg2=30
t1:name2=wei
t1:id=139959759865600
main:t1 exit,wei
*/
2.2、互斥锁pthread_mutex_init,pthread_mutex_destroy,pthread_mutex_lock,pthread_mutex_unlock
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr)
功能:创建锁
参数:
- 全局变量,指针
- 属性,NULL
int pthread_mutex_destroy(pthread_mutex_t *mutex)
功能:销毁锁
参数:全局变量,指针
int pthread_mutex_lock(pthread_mutex_t *mutex)
功能:加锁
参数:全局变量,指针
int pthread_mutex_unlock(pthread_mutex_t *mutex)
功能:解锁
参数:全局变量,指针
例子:
-
全局变量data和锁变量
-
创建锁,创建2个线程
-
2线程函数
-
1: 加锁,循环data++,sleep延时1s,if3解锁退出线程
-
2:死循环输出data,加锁data++,解锁,延时1s
-
主函数,打印data,等待线程
-
销毁锁
注:线程2加锁是因为锁被线程1拿了,没有锁拿就会卡在那里。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int data = 0;
pthread_mutex_t nutex;
void *fun1(void *arg)
{
printf("t1:id=%ld\n",(unsigned long)pthread_self());
pthread_mutex_lock(&nutex);
while(1){
data++;
printf("t1:data=%d\n",data);
if(data == 3){
printf("t1 quit =============================\n");
pthread_mutex_unlock(&nutex);
pthread_exit(NULL);
}
sleep(1);
}
}
void *fun2(void *arg)
{
printf("t2:id=%ld\n",(unsigned long)pthread_self());
while(1){
pthread_mutex_lock(&nutex);
data++;
pthread_mutex_unlock(&nutex);
printf("t2:data=%d\n",data);
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
pthread_t t1;
pthread_t t2;
int arg = 100;
pthread_mutex_init(&nutex, NULL);
if(pthread_create(&t1, NULL, fun1, (void *)&arg) == 0){
printf("found thread succeed\n");
}
if(pthread_create(&t2, NULL, fun2, (void *)&arg) == 0){
printf("found thread succeed\n");
}
printf("main:id=%ld\n",(unsigned long)pthread_self());
while(1){
printf("main:%d\n",data);
sleep(1);
}
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&nutex);
return 0;
}
/*
found thread succeed
t1:id=140562014590720
t1:data=1
found thread succeed
main:id=140562023094080
main:1
t2:id=140562006198016
main:1
t1:data=2
t1:data=3
t1 quit =============================
main:2
t2:data=4
main:4
t2:data=5
t2:data=6
main:6
*/
2.3、条件pthread_cond_init,pthread_cond_destroy,pthread_cond_wait,pthread_cond_timewait,pthread_cond_signal,pthread_cond_broadcast
静态态初始化,pthread_cond_t cond = PTHREAD_COND_INITIALIER;
动态初始化,int pthread_cond_init(pthread_cond_t *cond, thread_condattr_t *cond_attr);
功能:创建
参数:全局变量,指针属性NULL
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
功能:等待
参数:cond,nutex
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:触发,广播
例子:
- 2个线程,锁,条件初始化
- 线程1等待条件
- 线程2加锁data++,触发条件
- 线程1执行
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int data = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t nutex = PTHREAD_MUTEX_INITIALIZER;
void *fun1(void *arg)
{
while(1){
pthread_cond_wait(&cond, &nutex);
printf("t1:%d\n",data);
data = 0;
}
}
void *fun2(void *arg)
{
while(1){
pthread_mutex_lock(&nutex);
data++;
pthread_mutex_unlock(&nutex);
printf("t2:data=%d\n",data);
if(data == 3){
pthread_cond_signal(&cond);
}
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&nutex, NULL);
pthread_create(&t1,NULL,fun1,NULL);
pthread_create(&t2,NULL,fun2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&nutex);
return 0;
}
/*
t2:data=1
t2:data=2
t2:data=3
t1:3
t2:data=1
t2:data=2
t2:data=3
t1:3
t2:data=1
t2:data=2
t2:data=3
t1:3
*/