Linux应用编程---4.pthread_create函数

Linux应用编程—4.pthread_create函数

​ 之前学习了进程有关的东西,现在学习如何创建一个线程。

4.1 pthread_create()函数详情

​ 线程创建函数是:pthread_create()。在Linux终端下,输入man pthread_create,查看函数定义以及使用方法。

image-20221123220839209

图1 pthread_create函数详情
NAME
       pthread_create - create a new thread

SYNOPSIS
       #include <pthread.h>

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

       Compile and link with -pthread.

​ 简单来看,pthread_create是用来创建一个线程,使用时需要包含头文件:pthread.h。函数返回值是int型,有4个入参。特别注意编译时,要加上-pthread。

The  pthread_create()  function starts a new thread in the calling process.  The new thread starts execution by invoking start_routine(); arg is passed as the sole argu‐
       ment of start_routine().

​ pthread_create()函数在调用进程内开始一个新的线程。这个新的线程开始执行是通过调用start_routine()函数。arg作为start_routine()的唯一参数传递。

The attr argument points to a pthread_attr_t structure whose contents are used at thread creation time to determine attributes for the new thread; this structure is ini‐
       tialized using pthread_attr_init(3) and related functions.  If attr is NULL, then the thread is created with default attributes.
Before  returning,  a  successful  call  to  pthread_create() stores the ID of the new thread in the buffer pointed to by thread; this identifier is used to refer to the
       thread in subsequent calls to other pthreads functions.

​ pthread_create()有4个入参,分别是:pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg。在函数return前,pthread_create()成功调用,新的线程保存它的id号到指针指向的缓存也就是thread,所以,第一个参数传入一个pthread_t类型的地址,用来保存新的线程的id。这个id后面创建其它线程时起作用。attr参数指向pthread_attr_t类型的结构体指针,其内容是线程创建时用于确定新线程的属性。如果attr 时null的话,这个线程创建时是默认属性。void *(*start_routine) (void *)是一个函数指针,是新线程执行的函数入口,arg作为start_routine()的唯一参数传递,如果不需要传递参数,赋值NULL即可。

ETURN VALUE
       On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.

​ 有关返回值,当pthread_create()创建函数成功时,返回0。

​ 以上就是关于pthread_create()函数的用法。

4.2 pthread_create()函数编程实践

#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void * thread_function(void *arg);

int main(void)
{
        int ret = 0;
        pthread_t thread;

        ret = pthread_create(&thread, NULL, thread_function, NULL);

        if(0 != ret)
        {
                perror("thread create.");
                exit(1);
        }

        return 0;
}

void * thread_function(void *arg)
{
        printf("Thread start running.\n");

        while(1)
        {
                printf("Hello world!\n");
                sleep(1);
        }
    
    return NULL;
}

​ 假如这个程序按照我们设想的方式执行,如果线程创建成功,则打印:Thread start running.Hello world每隔一秒钟打印一次。如果线程创建失败,则打印thread create.。但是,事实上运行结果是下图这样的:

image-20221123232533718

图2 代码运行结果

​ 没有任何现象!这是因为线程是从属于进程的。在线程创建结束后,main函数也执行到了return 0处,main函数就是调用进程,它结束后,系统资源被操作系统回收,线程也随之被回收。所以,运行没有结果。

​ 那么解决方法可以是,在线程没有执行结束后,进程要保持活跃的运行态。我们先简单粗暴的修改下代码。在main函数返回return 0之前,用while(1)将其阻塞。

image-20221123233219653

图3 用while(1)阻塞main函数

​ 此时,我们发现线程开始运行,每隔1秒打印一条语句。这里我们让进程保持运行状态,从而新建的线程也开始运行。但是,某些情况下,线程运行结束后,进程因为被while(1)阻塞,得不到释放。如何解决这个问题呢,在此,引入一个新的函数。

4.3 pthread_join()函数详情

​ 在终端输入man pthread_join,查阅该函数定义以及使用方法。

image-20221123233913927

图4 pthread_join函数详情
NAME
       pthread_join - join with a terminated thread

SYNOPSIS
       #include <pthread.h>

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

       Compile and link with -pthread.

​ pthread_join函数,返回值是int类型,函数调用成功时,返回值为0。入参有两个pthread_t thread, void **retval。

The  pthread_join() function waits for the thread specified by thread to terminate.  If that thread has already terminated, then pthread_join() returns immediately.  The
       thread specified by thread must be joinable.

       If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that the target thread supplied to pthread_exit(3)) into the  lo‐
       cation pointed to by retval.  If the target thread was canceled, then PTHREAD_CANCELED is placed in the location pointed to by retval.

​ pthread_join()函数用来等待线程结束,如果那个线程已经结束,该函数会立即返回。如果retval不为空指针,函数会将退出状态保存到retval里面。

#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void * thread_function(void *arg);

int main(void)
{
        int ret = 0;
        pthread_t thread;

        ret = pthread_create(&thread, NULL, thread_function, NULL);

        if(0 != ret)
        {
                perror("thread create.");
                exit(1);
        }

        pthread_join(thread, NULL);

        return 0;
}

void * thread_function(void *arg)
{
        int i = 0;
        printf("Thread start running.\n");

        for(i = 0; i < 5; i++)
        {
                printf("Hello world!\n");
                sleep(1);
        }

        return NULL;
}

​ 该代码利用pthread_join(thread, NULL)监测线程结束,然后返回。也就是只有线程结束,才停止阻塞进程,让进程保持运行。

​ 运行结果:

image-20221124003245132

图5 运行结果

​ 当线程中的打印语句每隔1秒打印1次,一共打印了5次后,线程结束,随之,进程也结束。pthread_join(thread, NULL)起到了作用。

4.4 进阶

​ pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);arg作为start_routine()的唯一参数传递,那尝试用arg参数向进程传递参数。比如,传递线程中打印语句的打印次数。

#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void * thread_function(void *arg);

int main(void)
{
        int ret = 0;
        pthread_t thread;
        int count = 7;

        ret = pthread_create(&thread, NULL, thread_function, &count);

        if(0 != ret)
        {
                perror("thread create.");
                exit(1);
        }

        pthread_join(thread, NULL);

        return 0;
}

void * thread_function(void *arg)
{
        int i = 0;
        printf("Thread start running.\n");

        for(i = 0; i < *((int *)arg); i++)
        {
                printf("Hello world!\n");
                sleep(1);
        }

        return NULL;
}

​ 运行结果:

image-20221124003852061

图6 运行结果

​ 我们定义了int型变量count,然后在pthread_create(&thread, NULL, thread_function, &count);中将其地址传入,在线程函数内,这个值被取出,并参与了循环终止条件的判断。根据结果来看,运行是正确的。

4.4 总结

​ 线程创建函数:pthread_create,以及它的入参的含义。线程是从属于进程的,进程结束线程也随之结束。阻塞式等待线程结束可以调用pthread_join()函数。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值