线程的相关函数:创建、属性、接合、退出类型......

一. 进程与线程关系

进程: ./xxx --> 开启一个新的进程 进程是系统最小资源分配单位

int main() { --> 进程开始 …

return 0; --> 进程结束 }
线程: 一个进程内部的资源,是系统中调度的基本单位,所有子线程都是共有资源

二. 线程的函数接口 --> 封装在线程库 libpthread.so 头文件: pthread.h

库的路径: /usr/lib/i386-linux-gnu/libpthread.so
头文件的路径: /usr/include/pthread.h

三. 关于线程的函数接口

1. 创建一个新的线程 – pthread_create --> man 3 pthread_create

#include <pthread.h>

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

//使用了该函数,就必须在编译时链接线程库 -lpthread Compile and link with -pthread.

例子: gcc create.c -o create -lpthread

thread: 新的线程的TID号
attr: 线程的属性;普通属性: NULL
start_routine: 线程的任务函数
arg: 主线程传递子线程的参数

返回值: 	成功:0     ,并且线程创建了 	
失败:错误码,并且线程没有创建

=================================================================

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

//子线程的任务函数
void *fun(void *arg)
{
	int i;
	printf("I am child thread!\n");
	for(i=10;i>0;i--)
	{
		sleep(1);
		printf("child i = %d\n",i);
	}
}

int main()
{
	pthread_t tid; //用于存放子进程的TID号
	int ret;
	
	//主线程
	printf("I am main thread! before create!\n");
	
	ret = pthread_create(&tid,NULL,fun,NULL);
	if(ret != 0)
	{
		printf("pthread_create error!\n");
	}
	
	printf("I am main thread! after create!\n");
	
	int i;
	for(i=10;i>0;i--)
	{
		sleep(1);
		printf("main thread i = %d\n",i);
	}
	
	return 0;
}

2. 接合线程 — 回收子线程的资源 — pthread_join() – man 3 pthread_join

#include <pthread.h>

   int pthread_join(pthread_t thread, void **retval);

thread: 需要进行接合的子线程的TID号 retval: 存储子线程退出值的指针 如果填NULL,则不关注子线程的退出状态

返回值: 成功:0 失败:错误码

3. 线程的退出 — pthread_exit() — man 3 pthread_exit

#include <pthread.h>

   void pthread_exit(void *retval);

retval: 子线程退出值 地址不能是局部变量

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

int exit_state = 5;

//子线程的任务函数
void *fun(void *arg)
{

	printf("I am child thread!\n");
	
	pthread_exit(&exit_state);
	
}

int main()
{
	pthread_t tid; //用于存放子进程的TID号
	int ret;
	void *p = NULL;
	
	//主线程
	printf("I am main thread! before create!\n");
	
	ret = pthread_create(&tid,NULL,fun,NULL);
	if(ret != 0)
	{
		printf("pthread_create error!\n");
	}
	
	printf("I am main thread! after create!\n");

	//阻塞地接合子线程
	//pthread_join(tid,NULL);
	pthread_join(tid,&p);
	
	//p是指向退出值指针,只需要解引用p就可以,但是p是void* ,退出是int *  ,需要强转类型才能正常解引用
	printf("exit state = %d\n",*(int *)p);
	
	return 0;
}

4. 线程属性 – 分离属性

分离: 主线程不需要调用pthread_join去接合子线程
非分离: 主线程需要调用pthread_join去接合子线程

4.1 属性变量 类型: pthread_attr_t
1) 定义一个属性变量

  pthread_attr_t attr;

2) 初始化属性变量 — pthread_attr_init — man 3 pthread_attr_init

  #include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);
attr: 未初始化的属性变量的地址

  返回值: 			成功: 0 			失败: 非0错误码

  pthread_attr_init(&attr);

3) 设置属性变量 — pthread_attr_setdetachstate – man 3
pthread_attr_setdetachstate

  #include <pthread.h>

   int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

  attr:  已经初始化过的属性变量 		
  detachstate: 属性 			
  PTHREAD_CREATE_DETACHED  --> 分离属性   --> 不需要pthread_join 			
  PTHREAD_CREATE_JOINABLE   --> 非分离属性 --> 需要pthread_join

4) 用这个属性变量创建的线程就是一个分离的线程

5) 销毁属性变量 — pthread_attr_destroy – man 3
pthread_attr_destroy

    #include <pthread.h>
   int pthread_attr_destroy(pthread_attr_t *attr);

  attr:  已经初始化过的属性变量

  返回值: 			成功: 0 			
  失败: 非0错误码

分离属性的创建:

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


void *fun(void *arg)
{
	printf("I am child thread!\n");
	
	pthread_exit(NULL);
}

int main()
{
	pthread_t tid;
	//1. 定义一个属性变量
	pthread_attr_t attr;
	
	//2. 初始化属性变量
	pthread_attr_init(&attr);
	
	//3. 设置分离属性,主线程不关注子线程退出状态,子线程结束自动释放资源
	pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
	
	//4. 创建一个新的子线程
	pthread_create(&tid,&attr,fun,NULL);
	
	//5. 销毁属性变量
	pthread_attr_destroy(&attr);
	
	pause();
	
	return 0;
}

补充: 给线程设置分离属性 – pthread_detach()

//线程自己给自己设置一个分离属性 #include <pthread.h>

   int pthread_detach(pthread_t thread);

thread: 需要设置分离属性的TID号

//获取自身的TID号
#include <pthread.h>

   pthread_t pthread_self(void);

返回值: 返回线程自身ID号

#include<stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <semaphore.h> 
#include <fcntl.h>           
#include <sys/stat.h>

#include<stdlib.h>
void *fun(void *arg)
{
	//给自己设置一个分离属性
	pthread_detach(pthread_self());
	
	//退出时自动释放资源
}


int main()
{
	pthread_t tid;
	pthread_create(&tid,NULL,fun,NULL);
	
	pause();
}

5. 线程的取消 — pthread_cancel – man 3 pthread_cancel

#include <pthread.h>

   int pthread_cancel(pthread_t thread);

thread: 线程的ID号

返回值: 成功: 0 失败: 错误码

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

void *fun(void *arg)
{
	sleep(5);
	printf("I am child thread!\n");
	
	pthread_exit(NULL);
}

int main()
{
	pthread_t tid;
	pthread_create(&tid,NULL,fun,NULL);
	
	sleep(1);
	
	pthread_cancel(tid);
	printf("I send cancel to child!\n");
	
	pthread_join(tid,NULL);
	
	return 0;
}

6. 设置线程的取消响应行为
1) 设置取消信号响应使能: 响应取消/不响应取消
线程创建后,默认是响应取消信号,立即响应信号

  #include <pthread.h>

   int pthread_setcancelstate(int state, int *oldstate);

state: PTHREAD_CANCEL_ENABLE --> 使能取消
PTHREAD_CANCEL_DISABLE --> 不使能取消 oldstate: 原来的状态,不关注则填一个NULL

2) 设置取消响应是立即取消,还是延迟取消!

int p取消thread_setcanceltype(int type, int *oldtype);

  type: PTHREAD_CANCEL_DEFERRED   延后取消
         PTHREAD_CANCEL_ASYNCHRONOUS   立即取消

延后取消: 遇到取消点才响应取消
取消点:为一个函数,运行完取消点函数后,子线程被取消,取消点规则详见https://linux.die.net/man/7/pthreads

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

void *fun(void *arg)
{
	//pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);//延后取消,即遇到取消点时取消,会运行取消点
	//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); //立即取消
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);	//不能取消
	//sleep(5);
	//printf("I am child thread!\n");
	
	long long int i,j;
	for(i=0;i<10000;i++)
	{
		for(j=0;j<1000000;j++)
		{
			//printf("I am child thread!\n");
		}	
	}
	
	while(1)
	{
		//fputc('h',stderr); //取消点(标准输出)
		printf("I am child thread!\n");
	}
	
	pthread_exit(NULL);
}

int main()
{
	pthread_t tid;
	pthread_create(&tid,NULL,fun,NULL);

	pthread_cancel(tid);
	printf("I send cancel to child!\n");
	
	pthread_join(tid,NULL);
	
	return 0;
}

版权声明:本文为weixin_48256350原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。