Linux多线程的创建和结束

线程,是一个并发的执行流程,一般称之为轻量级的进程。

线程从属于创建他的进程,不和进程分离,共享进程资源。

创建线程的进程结束了,该进程的所有简称都结束(皮之不存毛将焉附)。

线程是cpu最小的执行单元。

线程的创建:

//Linux Programmer`s Manual
#include<pthread.h>

int pthread_create(pthread_t *thread,const pthread_attr_t *attr,
                void *(*start_routine) (void *),void *arg);//创建一个新的线程

/*
参数1:线程的标识符(其实就是int)  参数2:设置线程的属性(分离or非分离)
参数3:线程要执行的函数(返回值和形参类型都固定死了(void *))
参数4:线程执行的时候,要传给线程的参数。

compile and link with -pthread  编译的时候要加上 -pthread
eg:    gcc text.c -o s -pthread

成功返回0。
失败返回一个参数编号error number。
没有对全局错误变量设置值,不能用perror打印错误信息。(perror->errno)
可以把error number传到strerror()中获得错误信息。

分离:线程结束后,(进程)进行资源回收。
非分离:(进程)不进行资源回收。
*/

测试1: 主进程和2个线程并发执行>>>>>>>>>>>>>线程的创建。

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

void *thread_one(void *arg)
{
    int num = (int)arg;
    while(num > 0)
    {
        printf("int thread one ->%d\n",num--);
        sleep(1);
    }
    return NULL;
}

void *thread_two(void *arg)
{
    int num = (int)arg;
    while(num > 0)
    {
        printf("int thread two ->%d\n",num--);
        sleep(1);
    }
    return NULL;
}

int main(void)
{
    //线程的标识
    pthread_t one;        //线程的标识符 long unsigned int
    //参数2:设置线程的属性,分离,栈空间大小,优先级,调度策略..
    //参数3:执行函数
    //参数4:成功为0,失败为错误编号:注意 不是errno
    int ret = pthread_create(&one,NULL,thread_one,(void*)10);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
    //strerror()捕获错误信息,以字符串str类型返回。
    //他不会设置全局错误变量,所以perror不能用。
    //因为线程的创建函数不属于 系统调用,属于 用户层 的函数,所以不会对errno进行设置。
        exit(EXIT_FAILURE);
    }
    printf("pthread_one=%lu\n", one);
    pthread_t two;   
    int ret = pthread_create(&two,NULL,thread_two,(void*)15);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));    
        exit(EXIT_FAILURE);
    }

    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
    }                      //第三个并发的执行流程。
    return 0;
}

测试2:线程的结束。

线程的结束方式:

1,线程函数执行完了,运行return返回  (寿终正寝)

2,线程运行过程中,满足某个条件提前结束,pthread_exit (吊日子过不下去了)

3,线程A 收到 线程B 发送的结束请求,默认情况下,会结束执行结束请求,提前结束(谋害)

4,同归于尽的结束方式:在线程中调用exit。

1、2都是内部结束,3是外部结束。

线程结束处理:

线程有运行代码,有栈空间,TCB(线程控制块),线程号等...

线程结束后,需要对其进行资源回收。

---->pthread_join:阻塞等待指定的线程结束,并对其进行资源回收。

可以通过pthread_join 获得线程的返回值。

//man手册中的pthread_join
#include<pthread.h>
int pthread_join(pthiread_t thread,void **retval);

 正常结束return:

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

void *thread_one(void *arg)
{
    int num = (int)arg;
    while(num > 0)
    {
        printf("int thread one ->%d\n",num--);
        sleep(1);
    }
    return (void* 66);
}

int main(void)
{
    //线程的标识
    pthread_t one;        
    int ret = pthread_create(&one,NULL,thread_one,(void*)5);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    printf("pthread_one =%lu\n",one);

    //阻塞等待指定的线程结束,并对其进行资源回收
    void *retval=NULL;
    pthread_join(one,&retval);
    printf("thread retval = %d\n",(int)retval);

    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
    }                      //第三个并发的执行流程。
    return 0;
}

非正常结束

pthread_exit();

//man手册
#include<pthread.h>
void pthread_exit(void *retval);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>

void *thread_one(void *arg)
{
    int num = (int)arg;
    while(num > 0)
    {
        printf("int thread one ->%d\n",num--);
        sleep(1);
        if(2==num)
        {
            //结束线程本身,不影响其他。
            pthread_exit((void*)88);
        }
    }
    printf("end of thread\n");
    return (void* 66);
}

int main(void)
{
    //线程的标识
    pthread_t one;        
    int ret = pthread_create(&one,NULL,thread_one,(void*)5);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    printf("pthread_one =%lu\n",one);

    //阻塞等待指定的线程结束,并对其进行资源回收
    void *retval=NULL;
    pthread_join(one,&retval);
    printf("thread retval = %d\n",(int)retval);

    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
    }                      //第三个并发的执行流程。
    return 0;
}

结束请求:

pthread_cancel();

//man手册
#include <pthread.h>
int pthread_cancel(pthread_t thread);

//成功返回0 失败返回 nonzero error number
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>

void *thread_one(void *arg)
{
    int i = 0;
    while(1)
    {
        printf("int thread one ->%d\n",++i);
        sleep(1);
    }
    return (void* 66);
}

int main(void)
{
    //线程的标识
    pthread_t one;        
    int ret = pthread_create(&one,NULL,thread_one,NULL);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    printf("pthread_one =%lu\n",one);

    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
        
        if(5 == i)
        {
            //向指定的线程发出结束请求
            pthread_cancel(one);   
        }
    }                      //第三个并发的执行流程。
    return 0;
}

线程对请求的处理:

pthread_setcaacelstate();

pthread_setcancelstate();

//man
#include<pthread.h>
int pthread_setcancelstate(int state,int *oldstate);
state:PTHREAD_CANCEL_ENABLE  允许接收请求(默认)
      PTHREAD_CANCEL_DISABLE   阻塞
*oldstate: 是否要保存原先的state yes:任意int  no:给NULL
返回值:成功返回0  不成功返回 nonzero error number


int pthread_setcanceltype(int type,int *oldtype);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>

void *thread_one(void *arg)
{
    int i = 0;
    //收到的请求将会被阻塞,直到cancel的状态被设置为ENABLE
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
    while(1)
    {
        printf("int thread one ->%d\n",++i);
        sleep(1);
        if(15 == i)
        {
            printf("15s解除阻塞..\n");
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
        }
    }
    return (void* 66);
}

int main(void)
{
    //线程的标识
    pthread_t one;        
    int ret = pthread_create(&one,NULL,thread_one,NULL);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    printf("pthread_one =%lu\n",one);

    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
        
        if(5 == i)
        {
            //5S向指定的线程发出结束请求
            printf("发送结束请求..\n");
            pthread_cancel(one);   
        }
    }                      //第三个并发的执行流程。
    return 0;
}

线程属性的设置:

1.分离线程/非分离:

pthread_detach();//设置分离

//man
#include<pthread.h>
int pthread_detach(pthread_t thread);
//设置线程为分离线程,分离的线程结束后,资源自动回归系统,不需要等待资源回收
//如果分离一个已经分离的线程 会发生未知行为

成功返回0  不成功返货 nonzero error number

   //获得线程号 

    pthread_self()
    pthread_detach(pthread_self());//设置分离

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

void *thread_one(void *arg)
{
    pthread_detach(pthread_self());
    int i = 0;
    while(num > 0)
    {
        printf("int thread one ->%d\n",++i);
        sleep(1);
        if(5==i)
        {
            break;
        }
    }
    return (void* 66);
}

int main(void)
{
    //线程的标识
    pthread_t one;        
    int ret = pthread_create(&one,NULL,thread_one,(void*)5);
    if(0 != ret)
    {
        printf("create thread one failed --> %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    printf("pthread_one =%lu\n",one);

    //阻塞等待指定的线程结束,并对其进行资源回收
    void *retval=NULL;
    pthread_join(one,&retval);
    printf("thread retval = %d\n",(int)retval);
    
    int i = 0;
    //进程称之为主线程。
    while(1)
    {
        printf("in main while -->%d\n",++i);
        sleep(1);
    }                      //第三个并发的执行流程。
    return 0;
}

以上程序还是join成功了,因为线程创建成功后,会先执行join(不能在join前sleep(1),若sleep(1)的话,会让出CPU去执行线程,就会先执行detach。然后再执行join),再执行detach!(detach写入线程内部的情况)

join失败:

在join之前设置线程分离。

    pthread_detache(one);
    //阻塞等待指定的线程结束,并对其进行资源回收
    void *retval=NULL;
    pthread_join(one,&retval);
    printf("thread retval = %d\n",(int)retval);

**也可以在创建的时候 直接设置分离属性:

设置分离属性函数:pthread_attr_setdetachstate();

//man
#include<pthread.h>
pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);

//detachstate:PTHREAD_CREATE_DETACHED
              PTHREAD_CAEATE_DETACHED

pthread_attr_getdetachstate(pthread_attr_t *attr,int detachstate);//获得分离属性
pthread_attr_t attr; //设置属性的变量
pthread_attr_init(&attr);//初始化
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//生成分离属性
int ret = pthread_create(&one,&attr,thread_one,NULL);//设置分离

设置优先级:

//man
#include<pthread.h>
int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);

int pthread_attr_getschedparam(pthread_attr_t *attr,const struct sched_param *param);

struct sched_param{
    int sched_priority; //根据这个整数来确定优先级
}
pthread_attr_t attr; //设置属性的变量
pthread_attr_init(&attr);//初始化

struct sched_param param;
param.sched_priority = ;

pthread_attr_setschedparam(&attr,&param);
if(0 != errnum)
{
    printf("设置优先级失败--->%s\n",strerror(errnum));
    exit(EXIT_FAILURE);
}

/*------------------------------------------------------------------------------------*/

笔记从2021.8.14开始记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值