头文件:#include <pthread.h>
线程创建:pthread_create
int
pthread_create(pthread_t *tidp,
const
pthread_attr_t *attr,void
*(*start_rtn)(
void
*),
void
*arg);
线程退出:pthread_exit
互斥锁:pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock、pthread_mutex_destroy
信号量:sem_init、sem _wait、sem _post、sem _trywait、sem_destroy
pthread_join:子线程合入主线程,主线程阻塞。
pthread_detach:主线程与子线程分离,主线程非阻塞。
线程属性:pthread_attr_t
初始化线程属性:pthread_attr_init
销毁线程属性:pthread_attr_destroy
通过属性修改线程的分离状态:pthread_attr_setdetachstate
通过属性获取线程的分离状态:pthread_attr_getdetachstate
一、主线程与子线程分离
/* pthread_detach非阻塞。子线程可能没完成运行,主线程就退出了。需要用while(1)阻塞主线程,才能保证完成执行子线程。 */
#include <stdio.h>
#include <pthread.h>
void *thread_function(void *arg)
{
printf("thread_function\n");
/*arg即是data*/
pthread_exit(NULL);
}
void main(void)
{
void *data;
pthread_t tid = 0;
if (0 != pthread_create(&tid, NULL, thread_function, data))
{
printf("Failed to create thread_function thread\n");
}
pthread_detach(tid);
while(1) sleep(10);
}
二、子线程合入主线程
/* pthread_join阻塞。不需要用while(1)阻塞主线程,子线程运行完成退出后,才会继续执行主线程。 */
#include <stdio.h>
#include <pthread.h>
void *thread_function(void *arg)
{
printf("thread_function\n");
/*arg即是data*/
pthread_exit(NULL);
}
void main(void)
{
void *data;
pthread_t tid = 0;
if (0 != pthread_create(&tid, NULL, thread_function, data))
{
printf("Failed to create thread_function thread\n");
}
pthread_join(tid, NULL);
}
参考:![](https://img-blog.csdnimg.cn/direct/ea7cf87fbb1c43128d094a5e0e5156b8.png)
Linux线程退出、资源回收、资源清理的方法 - CTHON - 博客园
为什么要将线程设置成分离状态_poison_biti的博客-CSDN博客_线程分离有什么用
Linux之线程:控制与分离_剩蛋君的技术博客_51CTO博客
用户态线程和内核态线程的区别 - 拾月凄辰 - 博客园 (cnblogs.com)
线程同步(互斥锁与信号量的作用与区别) - 木木ing - 博客园 (cnblogs.com)
linux中pthread_join()与pthread_detach()详解_魏波-的博客-CSDN博客_pthread_detach
多线程操作 pthread_create pthread_join_江太翁的博客-CSDN博客
pthread_attr_setdetachstate_明潮的博客-CSDN博客
posix多线程有感--线程高级编程(线程属性pthread_attr_t) - 胡永光 - 博客园 (cnblogs.com)
三、避免内存泄漏
在 POSIX 线程(pthread)库中,默认情况下,通过 pthread_create 创建的线程是 joinable 的,而不是分离的(detached)。这意味着这些线程在执行完成后并不会自动释放其资源。为了避免资源(如线程的堆栈)泄漏,其他线程需要调用 pthread_join 函数来等待这些线程结束,并回收它们占用的资源。
为了避免内存泄漏,可以采取以下步骤:
1. 调用 pthread_join:
最直接的方式是在确保线程完成的情况下,在创建线程的程序中调用 pthread_join 函数。
pthread_t thread;
// 创建线程
pthread_create(&thread, NULL, thread_function, NULL);
// ... do some work ...
// 等待线程结束
pthread_join(thread, NULL);
2. 分离线程(pthread_detach):
如果不想等待特定的线程结束,可以在创建线程之后立即将其设置为分离状态。
pthread_t thread;
// 创建线程
pthread_create(&thread, NULL, thread_function, NULL);
// 将线程设置为分离状态
pthread_detach(thread);
这样线程结束时会自动释放其资源,但随之也丧失了对该线程的额外控制,因为一旦线程分离,就无法再用 pthread_join 来同步了。
3. 使用线程属性 (pthread_attr_t):
可以通过设置线程属性来使线程在创建时就是分离状态的。
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 创建线程
pthread_create(&thread, &attr, thread_function, NULL);
// 销毁线程属性对象
pthread_attr_destroy(&attr);
在某些情形中,可能在设计应用程序时就考虑到线程管理的问题,确保在恰当的时候回收线程资源或不再需要时分离线程,从而避免内存泄漏。
当一个线程被设置为分离状态(detached)时,该线程完成执行后会自动清理其占用的资源,包括线程描述符和堆栈。因此,从操作系统的视角来看,这个线程在结束时不再需要其他线程对它进行任何形式的同步或管理操作。然而,这种自动清理带来的便利性是以牺牲某些控制功能为代价的,具体来说包括:
1. 无法同步线程结束:不能通过 pthread_join 等待这个线程结束。在非分离状态的线程中,`pthread_join` 会阻塞调用它的线程,直到目标线程结束。对于分离状态的线程,一旦它们结束,就不存在可以等待其结束的方法。
2. 无法获取退出状态:因为无法使用 pthread_join,所以也就无法获取线程的退出状态。`pthread_join` 的一个功能是允许调用者获取被等待线程的退出代码,这对于从线程传递执行结果回主线程是非常有用的。
3. 资源回收仅限于线程退出:线程只有在执行完成后才会清理资源。如果线程执行了一个长时间的操作或是因其他任何原因变得不响应(例如陷入死锁),那么这些资源将不会被释放,除非线程最终结束。
将线程设置为分离状态适合那些不需要与其他线程同步,且其运行结果不需要被其他线程获取的场景。这样的线程可以被认为是完全独立的,他们自己管理自己的生命周期,从而简化应用程序的线程管理逻辑。但如果需要更细致的管理或同步多个线程的工作,刚创建的线程应该保持为可连接(joinable)状态,并且在适当的时候调用 pthread_join 进行资源的回收和同步操作。