线程创建&回收:pthread_creat和pthread_join

一、pthread_creat函数

(一)定义1

位置:rt-thread > components > libc > pthreads > pthread.h

参见:RT-Thread标准版==>组件==>C库==>POSIX==>Pthread线程

总述:pthread_create是(Unix、Linux、Mac OS X)等操作系统的创建线程的函数。它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。

pthread_create的返回值表示成功,返回0;表示出错,返回表示-1

#include <pthread.h>
int pthread_create(
                 pthread_t *restrict tidp,   //新创建的线程ID指向的内存单元。
                 const pthread_attr_t *restrict attr,  //线程属性(非分离/分离),默认为NULL
                 void *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行
                 void *restrict arg //默认为NULL。若上述函数需要参数,将参数放入结构中并将地址作为arg传入。
                  );

1.传递参数注意的问题
问题:
避免直接在传递的参数中传递发生改变的量,否则会导致结果不可测。
即使是只再创造一个单线程,也可能在线程未获取传递参数时,线程获取的变量值已经被主线程进行了修改。

通常解决方案:
重新申请一块内存,存入需要传递的参数,再将这个地址作为arg传入。

2.使用时注意防止内存泄漏
在默认情况下通过pthread_create函数创建的线程是非分离属性的,由pthread_create函数的第二个参数决定,在非分离的情况下,当一个线程结束的时候,它所占用的系统资源并没有完全真正的释放,也没有真正终止

如果要保证创建线程之后,确保无内存泄漏,必须采用如下方法来规范pthread_create的使用。

(二)定义2

pthread_create()是一个POSIX线程函数,用于创建一个新线程。

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

这个函数创建新线程的主要步骤为:

1. 检查传入的线程属性attr是否正确,如果为空则使用默认属性。

2. 将start_routine函数和参数arg封装为线程任务。 

3. 系统将分配资源为新线程创建环境,并保存线程ID到thread参数。

4. 新创建的线程会调用start_routine(arg)函数开始执行线程任务。 

5. 如果资源分配成功,pthread_create()返回0,否则返回错误码。

使用这个函数创建新线程的步骤: 

1. 定义线程任务函数,其原型为`void func(void )`,用于线程执行体。 

2. 确定线程任务函数的参数(如果需要)。可以将参数封装在一个结构体中。

3. 声明一个线程ID变量,类型为pthread_t。

4. 调用pthread_create()函数,传入线程ID变量的地址,线程属性,线程任务函数名和参数。

5. 如果返回0,表示线程创建成功,线程ID变量会被保存新线程的ID。否则表示创建失败。

6. 主线程和新创建的线程会并发执行各自的任务。

7. 可以通过pthread_join()函数回收线程资源,并获取线程返回值。

所以,该函数实现了创建 POSIX 线程和执行线程任务的功能。我们可以利用这个功能在程序中添加并发执行的线程,实现多任务处理

使用这个线程创建函数需要注意:

1. 线程任务函数和参数必须正确,否则线程行为未定义。

2. 必须提供线程ID变量的存储空间,否则无法获取新线程的ID。

3. 线程创建需要一定的系统资源,如果资源不足会导致创建失败。

4. 新创建的线程会与主线程并发执行,需要注意同步和互斥避免问题。

 5. 线程创建后,需要回收线程资源来避免资源泄漏,一般在线程结束时join。

6. 实现细节依赖具体操作系统,移植性较差。POSIX线程只在Unixlike系统使用。

二、pthread_join函数

int pthread_join(
               pthread_t tid, //需要等待的线程,指定的线程必须位于当前的进程中,而且不得是分离线程
               void **status  //线程tid所执行的函数返回值(返回值地址需要保证有效),其中status可以为NULL
                 );
int pthread_join(pthread_t thread, void **retval);

这个函数回收线程资源的主要步骤为:

1. 检查传入的线程ID是否正确,必须是通过pthread_create()创建的线程ID。

2. 主线程会阻塞,直到指定的线程结束运行。

3. 系统会回收指定线程使用的所有资源,如线程环境、栈空间等。

4. 如果retval非空,则保存线程返回值到其指向的变量中。 

5. pthread_join()返回0表明成功加入线程,否则返回对应错误码。 

6. 被加入的线程会真正结束运行并被系统回收。

使用这个函数回收线程资源的步骤: 

1. 在pthread_create()创建线程时,获取新线程的ID,存储在pthread_t类型变量中。

2. 在主线程中,调用pthread_join(),传入要回收的线程ID和retval变量地址。

3. 主线程会阻塞,等待指定的线程结束运行。 

4. 系统会回收该线程的所有资源,并将线程的返回值保存到retval指向的变量。

5. pthread_join()返回0,表示成功回收线程资源。主线程继续运行。

6. 被加入的线程会完全结束,不会继续执行或占用资源。

所以,该函数实现了主线程等待其他线程结束运行并回收线程资源的功能。我们必须在主线程中调用pthread_join(),否则会出现线程资源泄漏。

使用这个线程资源回收函数需要注意:

1. 传入的线程ID必须是有效的,正在运行或已经结束运行的线程ID。否则返回错误。

2. 主线程会阻塞,直到目标线程结束。如果目标线程未结束,主线程会一直阻塞。

3. retval可以为空,在这种情况下丢弃线程的返回值。

4. 每个线程必须仅被一个pthread_join()函数join,否则结果未定义。

5. 没有被其他线程join的线程会成为僵尸线程,系统资源无法回收。

6. 实现细节依赖具体操作系统,移植性较差。

三、注:在RTThread中,使用pthread_creat创建的线程,与使用系统原生API:rt_thread_create和rt_thread_init创建的线程同样,不存在主线程or分线程的区别。

//创建动态线程
rt_thread_t rt_thread_create(const char* name,
                            void (*entry)(void* parameter),
                            void* parameter,
                            rt_uint32_t stack_size,
                            rt_uint8_t priority,
                            rt_uint32_t tick);

创建静态线程
rt_err_t rt_thread_init(struct rt_thread* thread,
                        const char* name,
                        void (*entry)(void* parameter), void* parameter,
                        void* stack_start, rt_uint32_t stack_size,
                        rt_uint8_t priority, rt_uint32_t tick);

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用`pthread_create`函数创建线程,你需要包含`pthread.h`头文件,并按照以下方式调用该函数: ```c #include <stdio.h> #include <pthread.h> void *thread_func(void *arg) { // 线程执行的代码 printf("Hello from new thread!\n"); return NULL; } int main() { pthread_t thread; int ret; // 创建线程 ret = pthread_create(&thread, NULL, thread_func, NULL); if (ret != 0) { printf("Failed to create thread: %d\n", ret); return 1; } // 等待线程结束 ret = pthread_join(thread, NULL); if (ret != 0) { printf("Failed to join thread: %d\n", ret); return 1; } printf("Thread finished.\n"); return 0; } ``` 在上面的代码中,定义了一个新线程的入口函数`thread_func`。然后,在`main`函数中,使用`pthread_create`函数创建一个新线程,并将线程函数`thread_func`作为参数传递给它。`pthread_create`函数的第一个参数是一个指向线程标识符的指针,用于存储新线程的ID。第二个参数是线程属性,这里我们传递了NULL表示使用默认属性。第三个参数是线程函数的指针,最后一个参数是传递给线程函数的参数。 创建线程成功后,我们使用`pthread_join`函数等待新线程的结束。`pthread_join`函数的第一个参数是要等待的线程ID,第二个参数是指向线程返回值的指针,我们在这里传递了NULL,因为在`thread_func`中没有返回值。 最后,我们输出一条消息表示主线程的执行已经结束。 希望这个例子能帮助到你!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值