线程及其相关知识(Linux)

目录

1.线程

2.创建线程

pthread_create函数

pthread_self函数

3.终止线程

pthred_exit函数

pthread_cancel函数

4.线程的连接与分离

pthread join 函数

pthread detach 函数


1.线程

        与进程类似,线程(thread)是允许程序并发执行多任务的一种机制。一个进程包含多个线程,每个线程会独立执行相同的程序代码,且共享同一份全局内存区域。

        同一进程中的多个线程可以并发执行。在多处理器环境下,多个线程可以同时并行。如果一个线程因等待I/O操作而堵塞,那么其他线程依然可以继续运行。

线程相对于进程的优势:

        1.进程间的信息难以共享,需要进程间通信。线程间能够方便、快速的共享信息,不管要避免多个线程修改同一数据的情况。

        2.调用fork函数创建进程的代价比较高,需要复制父进程的内容。线程比进程的创建要快的多。

2.创建线程

        启动程序时,产生的进程只有单条线程,称之为初始或者主线程。函数pthread_create()负责创建一条新的线程。新线程通过调用带有参数的arg函数start_routine而开始执行。调用pthread_create()的线程会继续执行该调用之后的语句。

        进程内部的每个线程都有一个唯一的标识,称为线程ID。线程获取自己的线程ID使用pthread_self()函数。

        使用ps-eLf查看线程

        使用gcc编译,要加参数lpthread

pthread_create函数

        函数描述:

                创建一个线程

        头文件:

                #include<pthread.h>

        函数原型:

                int pthread_create(pthread_t *thread,const pthread_attr *attr,void *(*strt_routine)(void*),void *arg );

        函数参数:

                thread:传出参数,保存系统为我们分配好的线程ID

                attr:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改参数

                start_routine:函数指针,指向线程主函数(线程体),该函数运行结束,则该线程结束

                arg:线程主函数参数

        函数返回值:

                成功返回0

                失败返回错误号

pthread_self函数

        函数描述:

                获取线程ID。类似与进程中的getpid函数。线程ID是进程内部的识别标识(两个进程间,运行线程ID相同)。

        函数原型:

                pthread_t pthread_self(void);

        函数返回值:

                成功返回线程ID,pthread_t为无符号整型(%lu)

                失败返回无

        例如下面一段代码,

int a=0;
void* thread1(void* arg){
    printf("thread tid=%lu\n",pthread_self());
    a=1;
    return NULL;
}
int main(int argc,char* argv[]){
    pthread_t tid;
    pthread_create(&tid,NULL,thread1,NULL);
    printf("main tid=%lu\n",pthread_self());
    sleep(1);
    printf("a=%d\n",a);
    return 0;
}

通过创建一个线程,让这个线程去修改a的值。

注意编译的语句为gcc -o fun fun.c -lpthread

3.终止线程

终止线程的方式

        1.线程start_routine函数执行return

        2.线程调用pthread_exit()函数

        3.任意线程调用exit(),或者主线程执行了return(在main函数中执行return)

        4.调用pthead_cancel()取消指定线程

        pthread_exit函数将终止调用线程,且其返回值可由另一线程调用pthread_join()来获取。调用pthread_exit()相当于在线程的start_routine函数中执行return,不同之处在于,可在线程start_routine函数所调用的任意函数中调用pthread_exit()都能够直接终止线程。

pthred_exit函数

        函数描述:

                终止线程

        函数原型

                void pthread_exit(void* retval);

        函数参数:

                retval:表示线程退出状态,通常传NULL;

例如在上述代码中修改一下thread1函数

int a=0;
void* thread1(void* arg){
    printf("thread tid=%lu\n",pthread_self());
    pthread_exit(NULL);
    a=1;
    return NULL;
}
int main(int argc,char* argv[]){
    pthread_t tid;
    pthread_create(&tid,NULL,thread1,NULL);
    printf("main tid=%lu\n",pthread_self());
    sleep(1);
    printf("a=%d\n",a);
    return 0;
}

在执行thread1这个线程时,就会打印后直接结束这个线程,而不会去执行后面的语句,所以a的值为0.

pthread_cancel函数

        函数描述:

                向指定线程发送一个取消请求。发出取消请求后,函数pthread_cancel()当即返回,不会等待目标线程的退出。被请求取消的线程不会立即取消,需要等待到达某一个取消点。被取消的线程返回值是PTHREAD_CANCELED(-1)

        函数原型

                int pthread_cancel(pthread_t thread);

        函数参数:

                thread:要取消的线程ID

        函数返回值:

                成功返回0

                失败返回错误号

int a =0;
void* thread1(void*arg){
    while(1){
        if (a == 10){
            a =0;
           }
        a++;
        pthread_testcancel();
    }
}
int   main(int argc,char* argv[]){
    pthread_t tid;
    pthread_create(&tid,NULL,threadl,NULL);
    int ret =pthread_cancel(tid);
    if (ret != 0)
        printf("pthread cacel error,ret = %d\n",ret);
    else
        printf("pthread cacel success,ret =%d\n",ret);
    while(1){
        printf("a=%d\n",a);
        sleep(1);    
    }        
}

        在主函数中,创建了一个线程,然后thread函数力扣执行,然后调用函数pthread_cancel函数取消,在thread1函数中,pthread_testcancel()函数是一个检测点,当发现有取消这个线程的请求时,就会终止这个线程。

4.线程的连接与分离

        当一个线程结束时,它所占用的系统资源(如栈空间等)不会立即被释放,而是处于一种 “僵尸” 状态,等待其他线程调用pthread_join来回收这些资源。如果不调用pthread_join,可能会导致资源泄漏,尤其是在频繁创建和销毁线程的情况下。

pthread join 函数

        函数描述:

                等待指定线程终止并回收,这种操作叫做连接(joining)。未连接的线程会产生僵尸线程,类似僵尸进程的概念。

        函数原型:

                int pthread join(pthread t thread, void **retval);

        函数参数:

                thread:要等待的线程ID

                retval:存储线程返回值

        函数返回值:

                成功返回 0

                失败返回错误号

int a=0;
void* thread1(void* arg)
{
    sleep(1);
    a++;
    return NULL;
}
int  main(int argc,char* argv[]){
    pthread_t tid;
    pthread_create(&tid,NULL,threadl,NULL);
    pthread_join(tid,NULL);
    printf("a=%d\n",a);
    return 0;
}

在这个函数中,将thread1函数连接,主线程只有等thread1函数执行结束后,才会结束自己。

pthread detach 函数

        函数描述:

                默认线程是可连接的(ioinable),当线程退出时,其他线程可以通过调用pthread join()获取其返回状态。有时,程序员并不关心线程的返回状态,只是希望系统在线程终止时能够自动清理并移除。这时可以调用 pthread detach()函数,将线程标记为分离(detached)状态。

        函数原型:

                int pthread detach(pthread t thread);

        函数参数:

                thread:要分离的线程ID

                retval:存储线程返回值

        函数返回值:

                成功返回 0

                失败返回错误号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值