系统编程 day07 (linux ) ( 线程的函数 等待,线程退出,取消执行的函数 ) pthread_join pthread_cancel pthread_exit

本文介绍了线程管理的基础知识,包括线程的创建、取消、退出及等待等函数的使用方法,并详细解释了互斥锁的创建、初始化、加锁、解锁等过程,最后展示了条件变量的使用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.函数 (三个 )

//1.pthread_join()  与wait 的功能相似  函数的功能: 等待另外一个线程的结束
//2.pthread_cancel  取消线程的执行  (取消执行的是传入的线程号)  
//3.pthread_exit()  线程退出函数 与 获得线程的状态的函数一起用(pthread_join)

函数:pthread_join

头文件: #include<pthread.h>

函数原型:int pthread_join( pthread_t tid, void **status );

函数功能:pthread_join() 会阻塞调用它的线程,直到参数 tid 指定的线程结束。 tid 指定的线程必须在当前进程中,且必须是非分离的。 status 接收指定线程终止时的返回状态码。 不能有多个线程等待同一个线程终止,否则返回错误码 ESRCH ,当 pthread_join() 返回时,终止线程占用的堆栈等资源已被回收。 返

回值:成功返回 0  


函数:pthread_cancel ()

头文件:pthread.h

原型:int  pthread_cancel( pthread_t thread );

参数:thread 为所要取消的线程

返回值:成功返回0,非0表示不成功

功能补充:一线程调用pthread_cancel函数向另一线程的发送一个取消信号,

pthread_cancel并不能结束其它进程,

一般使用了pthread_cancel之后再调用pthread_join

pthread_exit与pthread_cancel的区别: pthread_exit用于当前线程退出,而pthread_cancel是当前线程取消另一线程的执行


函数:pthread_exit

头文件:pthread.h

原型:void pthread_exit(void * value_ptr);

参数:value_ptr 线程返回值指针


代码:(注意编译的时候  加上  -pthread  或者  -lpthread) 

比如说: gcc  11.c  -pthread  -o  11

/************************************************************************************************************************************************************************************************************************
 *文件名:
 *作  者:She001
 *时  间:
 *版  本:
 *作  用:pthread_join 函数的使用 
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#include<a.out.h>
#include<signal.h>
#include<stdarg.h>
#include<sys/socket.h>
#include<utime.h>
#include<sys/utsname.h>
#include<sys/times.h>
#include<sys/un.h>
#include<ctype.h>
#include<dirent.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<syslog.h>
#include<pthread.h>
//1.pthread_join()  与wait 的功能相似  函数的功能: 等待另外一个线程的结束
//2.pthread_cancel  取消线程的执行  (取消执行的是传入的线程号)  
//3.pthread_exit()  线程退出函数 与获得线程的状态的函数一起用
void * pthread_fun1(void *arg)//创建线程的函数 
{
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<10;i++)
	{
		printf("this is pthread_join test\n");
		sleep(1);
	}


	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());

	pthread_exit((void *)1);//线程退出函数: 常量强转成指针
	//return NULL;
}

int main(int argc,char *argv[])
{

	
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	pthread_t tid =0;
	pthread_create(&tid,NULL,pthread_fun1,NULL);
	
	
	sleep(2);
	pthread_cancel(tid); //取消线程的执行  



	//pthread_join(tid,NULL); //不接受子线程的退出状态
	//void *ret;



	//pthread_join(tid,&ret); //接受子线程的退出状态
	//printf("this exit status is %lu\n",(long unsigned int )ret);
	//printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
       return 0;

}



程序功能:1.多线程抢占实验 : 主线程+3个线程  输出顺序是抢占的
                    2.多线程对公共的数据的访问,共享的

代码:(注意编译的时候  加上  -pthread  或者  -lpthread) 

比如说: gcc  11.c  -pthread  -o  11

/************************************************************************************************************************************************************************************************************************
 *文件名:
 *作  者:She001
 *时  间:
 *版  本:
 *作  用:
 		1.多线程抢占实验 : 主线程+3个线程  输出顺序是抢占的
 		2.多线程对公共的数据的访问,共享的
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#include<a.out.h>
#include<signal.h>
#include<stdarg.h>
#include<sys/socket.h>
#include<utime.h>
#include<sys/utsname.h>
#include<sys/times.h>
#include<sys/un.h>
#include<ctype.h>
#include<dirent.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<syslog.h>
#include<pthread.h>
int num=100;
void * pthread_fun1(void *arg)//创建线程的函数 
{
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num+=1;
		printf("1111111 :%d\n",num);
		sleep(1);
	}
	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());

}

void * pthread_fun2(void *arg)//创建线程的函数 
{
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num-=2;
		printf("22222222 :%d  \n",num);
		sleep(1);
	}

	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());

}

void * pthread_fun3(void *arg)//创建线程的函数 
{
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num+=3;
		printf("333333333 :%d\n",num);
		sleep(1);
	}
	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());

}

int main(int argc,char *argv[])
{

	
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	pthread_t tid1 =0;
	pthread_t tid2 =0;
	pthread_t tid3 =0;
	pthread_create(&tid1,NULL,pthread_fun1,NULL);
	pthread_create(&tid2,NULL,pthread_fun2,NULL);
	pthread_create(&tid3,NULL,pthread_fun3,NULL);
	
	
	pthread_join(tid1,NULL); //不接受子线程的退出状态
	pthread_join(tid2,NULL); //不接受子线程的退出状态
	pthread_join(tid3,NULL); //不接受子线程的退出状态






	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
       return 0;

}


//线程创建 锁的函数 pthread_mutex_init()
//线程加锁 的函数  pthread_mutex_lock()
//线程解锁 的函数  pthread_mutex_unlock();
//线程的摧毁锁的函数 pthread_mutex_destroy();

//pthread_mutex_trylock—测试锁

头文件:pthread.h

函数原型: int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr); 函数参数:  mutex:互斥锁。

Mutexattr :锁的类型 PTHREAD_MUTEX_INITIALIZER 创建快速互斥锁。 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 创建递归互斥锁。 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP  创建检错互斥锁。

函数返回值:成功:0;出错:-1


头文件:pthread.h

原型: int pthread_mutex_lock(pthread_mutex_t *mutex);

参数:mutex互斥id

返回值:成功返回0,不成功返回-1 功能补充:如果指定的互斥id已经被锁住那么呼叫线程在互斥id完全解锁前将一直处于挂起状态,否则将锁住互斥体

堵塞的函数!!!!!!!!!!


头文件:pthread.h

原型:int pthread_mutex_trylock(pthread_mutex_t *mutex);

参数:mutex互斥id

返回值:成功返回0,不成功返回-1,如果已经被其线程上锁则返回EBUSY(在errno.h中);

功能:如果指定的互斥id已经被锁住那么将直接返回一个错误,通过判断此错误来进行不同的处理,测试完之后会加锁

不会堵塞的函数!!!!!!!!


头文件:pthread.h

原型: int pthread_mutex_unlock(pthread_mutex_t *mutex);

参数:mutex互斥id

返回值:成功返回0,不成功返回-1


头文件:pthread.h

原型: int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数:mutex互斥id

返回值:成功返回0,不成功返回-1


程序功能: 抢占输出的时候 上锁 保护数据安全

         1.多线程抢占实验 : 主线程+3个线程  输出顺序是抢占的
         2.多线程对公共的数据的访问,共享的
        3.对公共化数据上锁,互斥锁

代码:

 

/************************************************************************************************************************************************************************************************************************
 *文件名:
 *作  者:She001
 *时  间:
 *版  本:
 *作  用:
 		1.多线程抢占实验 : 主线程+3个线程  输出顺序是抢占的
 		2.多线程对公共的数据的访问,共享的
		3.对公共化数据上锁,互斥锁
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#include<a.out.h>
#include<signal.h>
#include<stdarg.h>
#include<sys/socket.h>
#include<utime.h>
#include<sys/utsname.h>
#include<sys/times.h>
#include<sys/un.h>
#include<ctype.h>
#include<dirent.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<syslog.h>
#include<pthread.h>
//线程创建 锁的函数 pthread_mutex_init()
//线程加锁 的函数  pthread_mutex_lock()
//线程解锁 的函数  pthread_mutex_unlock();
//线程的摧毁锁的函数 pthread_mutex_destroy();
//
//
//使用的步骤 (锁的状态为结构体)
//1.创建锁
//2.初始化锁
//3.上锁
//4.读写操作
//5.解锁
//6.销毁锁


int main(int argc,char *argv[])
{

	
	//1.创建锁
	pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;
	


	//2.初始化锁
	if(pthread_mutex_init(&mutex,NULL)<0)
	{
		perror("pthrrad_mutex_init  error\n");
		return -1;
	}
	else
	{
		printf("pthread_mutex_init ok !\n");
	}
	//3.上锁

	if(pthread_mutex_lock(&mutex)<0)//上锁
	{
		perror("pthread_mutex_lock error\n");
		return -2;
	}
	else
	{
		printf("pthread_mutex_lock ok!\n");
	}
	int a;
#if 0
	a = pthread_mutex_unlock(&mutex); //解锁	
	printf("a=%d\n",a);
		if(!a)
		{
			printf("ulock ok!\n");
		}
		else
		{
			perror("unlock  error!\n");
		}
#endif
	//下面这个函数 已经上锁的话 会返回-1
	//没有上锁的话 ,会返回0 并且给你上锁	
	//测试函数 pthread_mutex_trylock   注意这里没有上锁后  函数会给你上锁
	while(pthread_mutex_trylock(&mutex))
	{
		perror("trylock error\n");
		sleep(1);
	}


	//4.读写操作
	


	//5.解锁
	 a = pthread_mutex_unlock(&mutex); //解锁	
	printf("a=%d\n",a);
		if(!a)
		{
			printf("ulock ok!\n");
		}
		else
		{
			perror("unlock  error!\n");
		}


	



	//6.销毁锁
	int b=pthread_mutex_destroy(&mutex);
	if(!b)
	{
		printf("destroy ok!\n");
	}
	else
	{
		printf("destroy error!\n");
	}


	return 0;

}

测试练习

 程序 功能: 在函数中实现 线程加锁解锁的功能

代码:

/************************************************************************************************************************************************************************************************************************
 *文件名:
 *作  者:She001
 *时  间:
 *版  本:
 *作  用:
 		1.多线程抢占实验 : 主线程+3个线程  输出顺序是抢占的
 		2.多线程对公共的数据的访问,共享的
		3.对公共化数据上锁,互斥锁
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#include<a.out.h>
#include<signal.h>
#include<stdarg.h>
#include<sys/socket.h>
#include<utime.h>
#include<sys/utsname.h>
#include<sys/times.h>
#include<sys/un.h>
#include<ctype.h>
#include<dirent.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<syslog.h>
#include<pthread.h>
//线程创建 锁的函数 pthread_mutex_init()
//线程加锁 的函数  pthread_mutex_lock()
//线程解锁 的函数  pthread_mutex_unlock();
//线程的摧毁锁的函数 pthread_mutex_destroy();
//
//
//使用的步骤 (锁的状态为结构体)
//1.创建锁
//2.初始化锁
//3.上锁
//4.读写操作
//5.解锁
//6.销毁锁
//程序的功能实现了每个操作的时候上锁
int num=100;
//1.创建锁 申请互斥锁
pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;









void * pthread_fun1(void *arg)//创建线程的函数 
{
	while(pthread_mutex_trylock(&mutex))
	{
		perror("fun1 trylock error\n");
		sleep(1);
	}
	int a;

	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num+=1;
		printf("1111111 :%d\n",num);
		sleep(1);
	}
	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
#if 1
	a = pthread_mutex_unlock(&mutex); //解锁	
	printf("a=%d\n",a);
		if(!a)
		{
			printf("fun1 ulock ok!\n");
		}
		else
		{
			perror("fun1 unlock  error!\n");
		}
#endif

}

void * pthread_fun2(void *arg)//创建线程的函数 
{
	while(pthread_mutex_trylock(&mutex))
	{
		perror("fun2 trylock error\n");
		sleep(1);
	}
	
	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num-=2;
		printf("22222222 :%d  \n",num);
		sleep(1);
	}

	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
	int  a = pthread_mutex_unlock(&mutex); //解锁	
	printf("a=%d\n",a);
		if(!a)
		{
			printf("fun2 ulock ok!\n");
		}
		else
		{
			perror("fun2 unlock  error!\n");
		}

}

void * pthread_fun3(void *arg)//创建线程的函数 
{
	while(pthread_mutex_trylock(&mutex))
	{
		perror("fun3 trylock error\n");
		sleep(1);
	}

	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	for(int i=0;i<5;i++)
	{
		num+=3;
		printf("333333333 :%d\n",num);
		sleep(1);
	}
	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
	int  a = pthread_mutex_unlock(&mutex); //解锁	
	printf("a=%d\n",a);
		if(!a)
		{
			printf("fun3  ulock ok!\n");
		}
		else
		{
			perror("fun3 unlock  error!\n");
		}

}

int main(int argc,char *argv[])
{

	


	//2.初始化锁
	if(pthread_mutex_init(&mutex,NULL)<0)
	{
		perror("pthrrad_mutex_init  error\n");
		return -1;
	}
	else
	{
		printf("pthread_mutex_init ok !\n");
	}



	printf("this is %s %d %ld start \n",__func__,getpid(),pthread_self());
	pthread_t tid1 =0;
	pthread_t tid2 =0;
	pthread_t tid3 =0;
	pthread_create(&tid1,NULL,pthread_fun1,NULL);
	pthread_create(&tid2,NULL,pthread_fun2,NULL);
	pthread_create(&tid3,NULL,pthread_fun3,NULL);
	

/*
	//下面这个函数 已经上锁的话 会返回-1
	//没有上锁的话 ,会返回0 并且给你上锁	
	//测试函数 pthread_mutex_trylock   注意这里没有上锁后  函数会给你上锁
	while(pthread_mutex_trylock(&mutex))
	{
		perror("trylock error\n");
		sleep(1);
	}

*/
	
	pthread_join(tid1,NULL); //不接受子线程的退出状态
	pthread_join(tid2,NULL); //不接受子线程的退出状态
	pthread_join(tid3,NULL); //不接受子线程的退出状态


	//6.销毁锁
	int b=pthread_mutex_destroy(&mutex);
	if(!b)
	{
		printf("destroy ok!\n");
	}
	else
	{
		printf("destroy error!\n");
	}

	printf("this is %s %d %ld end \n",__func__,getpid(),pthread_self());
  
	return 0;

}


线程唤醒功能的函数:pthread_cond_wait

                                        pthread_cond_signal

                                        pthread_cond_init


pthread_cond_init--初始化条件变量

头文件:pthread.h

原型:int pthread_cond_init(pthread_cond_t *cond,    pthread_condattr_t*cond_attr);

参数:使用 cond_attr 指定的属性初始化条件变量 cond,当 cond_attr 为 NULL 时,使用缺省的属性。LinuxThreads 实现条件变量不支持属性,因此 cond_attr 参数实际被忽略

返回值: 在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码

注意:pthread_cond_t 类型的变量也可以用 PTHREAD_COND_INITIALIZER 常量进行静态初始化。


pthread_cond_signal--启动线程

头文件:pthread.h

原型:int pthread_cond_signal(pthread_cond_t *cond);

参数:cond为条件变量,初始化了的条件变量

返回值:在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码 功能补充:使在条件变量上等待的线程中的一个线程重新开始。如果没有等待的线程,则什么也不做。如果有多个线程在等待该条件,只有一个能重启动,但不能指定哪一个


pthread_cond_wait--自动解锁互斥量并等待条件变量触发

原型: int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

参数:自动解锁互斥量(如同执行了 pthread__mutex_unlock),并等待条件变量触发。这时线程挂起,不占用 CPU 时间,直到条件变量被触发。在调用 pthread_cond_wait 之前,应用程序必须加锁互斥量。pthread_cond_wait 函数返回前,自动重新对互斥量加锁(如同执行了 pthread_mutex_lock)。

返回值:在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码


pthread_cond_broadcast--重启动等待该条件变量的所有线程

头文件:pthread.h

原型:int pthread_cond_broadcast(pthread_cond_t *cond);

参数:cond为条件变量,初始化了的条件变量

返回值:在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码 功能补充: 重启动等待该条件变量的所有线程。如果没有等待的线程,则什么也不做。


pthread_cond_timedwait--自动解锁互斥量并等待条件变量触发

原型:int   pthread_cond_timedwait(pthread_cond_t   *cond,    pthread_mutex_t *mutex, const struct timespec *abstime);

参数:cond为条件变量,mutex为互斥锁,abstime 参数指定一个绝对时间,时间原点与 time 相同

返回值:在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码


pthread_cond_destroy--销毁一个条件变量

原型:int pthread_cond_destroy(pthread_cond_t *cond);

参数:cond为条件变量

返回值:在执行成功时,所有条件变量函数都返回 0,错误时返回非零的错误代码

功能补充:pthread_cond_destroy 销毁一个条件变量,释放它拥有的资源。进入 pthread_cond_destroy 之前,必须没有在该条件变量上等待的线程。在 LinuxThreads 的实现中,条件变量不联结资源,除检查有没有等待的线程外,pthread_cond_destroy 实际上什么也不做。

注意:条件变量函数不是异步信号安全的,不应当在信号处理程序中进行调用。特别要注意,如果在信号处理程序中调用 pthread_cond_signal 或 pthread_cond_boardcast 函数,可能导致调用线程死锁。


代码:

/************************************************************************************************************************************************************************************************************************
 *文件名:
 *作  者:She001
 *时  间:
 *版  本:
 *作  用:
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

//一个线程等待,另一个线程唤醒。
//写一个线程1等待,线程2发送信号。	
//子线程等待5s后向主线程发送信号,让线程继续运行。
void* thread_fun(void* arg)
{
	printf("%s : start\n",__func__);
	//sleep(10);
	for(int i=1;i<=10;i++)
	{
		printf("+++++++++++++++++++++++++++\n");
		sleep(1);
	}
	pthread_cond_signal(&cond);
	//signal 唤醒一个  broadcast唤醒所有。
	printf("%s end\n",__func__);
	return NULL;
}
int main()
{
	//分析执行流程。
	pthread_t tid;
	//初始化立即条件变量
	pthread_cond_init(&cond,NULL);
	pthread_mutex_init(&mutex,NULL);
	//
	pthread_create(&tid,NULL,thread_fun,NULL);
	printf("%s : start\n",__func__);
	//在主线程中等待,在子线程中唤醒。
	//转让时间片,让子线程先运行。
	//处于等待的线程
	pthread_cond_wait(&cond,&mutex);//主线程开始等待
	//还是有一种顺序在。
	printf("main : do some thing to num \n");
	sleep(1);//等待线程的结束
	printf("%s : end\n",__func__);

	pthread_cond_destroy(&cond);//销毁条件变量
	pthread_mutex_destroy(&mutex);//销毁互斥锁

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值