一个简单的多线程 pthread_detach

http://blog.sina.com.cn/s/blog_4ef8be9f0100f606.html

#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
void print_message_function( void *ptr );
main ( )
{
       pthread_t thread1;
             while(1)
       {
                       pthread_create(&thread1,NULL,(void*)&print_message_function,(void *)0);
       printf("%d\n",thread1);
               }
       exit (0) ;
 }
void  print_message_function( void *ptr )
     pthread_detach(pthread_self());
       static int g;
       printf("%d\n", g++);
       pthread_exit(0) ;
 }

//pthread_detach(pthread_self());
//使线成分离出来。当这个线程执行完成任务后释放释放资源。不然它会保留退出状态,等待别人来取。

-------------------------

pthread_detach(threadid)和pthread_detach(pthread_self())没有什么区别吧!有很严格的区别吗???如果非要讲区别不可,我觉得应该是调用他们的线程不同~!
     pthread_detach(threadid)函数的功能是使线程ID为threadid的线程处于分离状态,一旦线程处于分离状态,该线程终止时底层资源立即被回收;否则终止子线程的状态会一直保存(占用系统资源)直到主线程调用pthread_join(threadid,NULL)获取线程的退出状态。
   通常是主线程使用pthread_create()创建子线程以后,一般可以调用pthread_detach(threadid)分离刚刚创建的子线程,这里的threadid是指子线程的threadid;如此以来,该子线程止时底层资源立即被回收;
   被创建的子线程也可以自己分离自己,子线程调用pthread_detach(pthread_self())就是分离自己,因为pthread_self()这个函数返回的就是自己本身的线程ID;

 

<think>我们正在讨论POSIX线程(pthread)中的两种设置线程分离状态的方法:创建时使用属性设置(PTHREAD_CREATE_DETACHED)和创建后使用pthread_detach函数。 根据引用,我们可以总结如下: 1. 创建时设置分离属性(PTHREAD_CREATE_DETACHED): 在创建线程之前,我们可以通过设置线程属性对象(pthread_attr_t)来指定线程的分离状态。这样创建的线程将直接以分离状态(detached)启动。 2. 创建后分离(pthread_detach): 也可以在创建线程后(此时线程通常为可连接状态,joinable),通过调用pthread_detach函数来将线程设置为分离状态。 注意:不能对同一个线程既设置分离状态又进行连接(pthread_join),也不能重复分离(多次调用pthread_detach)或对已经分离的线程再次分离,否则会返回错误(如EINVAL)。 用户提到的一个错误场景:在创建线程时已经设置了分离属性(PTHREAD_CREATE_DETACHED),然后又调用了pthread_detach(thread_id),导致返回错误22(即EINVAL)。这是因为线程已经处于分离状态,再次分离是不允许的。 因此,两种方法选择一种使用即可,不要同时使用。 下面我们将详细介绍两种方法的使用步骤: 方法一:使用PTHREAD_CREATE_DETACHED属性创建分离线程 步骤: 1. 初始化线程属性对象(pthread_attr_t)。 2. 设置分离状态属性为PTHREAD_CREATE_DETACHED。 3. 使用该属性创建线程。 4. 销毁线程属性对象。 示例代码: ```c #include <pthread.h> void* thread_function(void* arg) { // 线程执行的任务 return NULL; } int main() { pthread_attr_t attr; pthread_t thread; // 初始化属性 pthread_attr_init(&attr); // 设置分离状态 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 创建线程 if (pthread_create(&thread, &attr, thread_function, NULL) != 0) { // 处理错误 } // 销毁属性对象 pthread_attr_destroy(&attr); // 注意:由于线程是分离的,不需要调用pthread_join // 主线程可以继续执行其他任务,然后退出 return 0; } ``` 方法二:创建后分离(pthread_detach) 步骤: 1. 创建线程(默认是可连接状态,joinable)。 2. 调用pthread_detach函数将线程设置为分离状态。 或者,如引用[2]中提到的,在线程函数内部调用pthread_detach(pthread_self()),这样在创建后立即将自己分离。 示例1(在主线程中分离): ```c #include <pthread.h> void* thread_function(void* arg) { // 线程执行的任务 return NULL; } int main() { pthread_t thread; if (pthread_create(&thread, NULL, thread_function, NULL) != 0) { // 处理错误 } // 创建后立即分离 if (pthread_detach(thread) != 0) { // 处理分离错误 } // 主线程继续执行 return 0; } ``` 示例2(在线程函数内分离): ```c #include <pthread.h> void* thread_function(void* arg) { // 将自己设置为分离状态 pthread_detach(pthread_self()); // 线程执行的任务 return NULL; } int main() { pthread_t thread; if (pthread_create(&thread, NULL, thread_function, NULL) != 0) { // 处理错误 } // 主线程继续执行,注意此时不需要对thread进行join或detach操作 return 0; } ``` 注意事项: - 分离状态的线程在退出时会自动释放其资源,不需要其他线程调用pthread_join来回收资源。 - 不要对同一个线程同时使用两种分离方法(即创建时分离和创建后又调用pthread_detach),这样会导致错误(EINVAL)。 - 如果线程已经被分离,则不能再调用pthread_join来等待它,否则会导致未定义行为(通常也是错误)。 引用[3]中给出的pthread_detach的伪代码实现也说明了这一点:如果线程已经处于分离状态(flags包含PTHREAD_ATTR_FLAG_DETACHED),则返回EINVAL。 因此,用户遇到的问题就是在创建线程时已经通过属性设置了分离状态,然后又调用了pthread_detach,导致返回错误22(即EINVAL)。解决方法就是去掉其中一个即可。 总结: - 如果希望线程在创建时就处于分离状态,使用属性设置(PTHREAD_CREATE_DETACHED)。 - 如果希望线程在创建后由主线程或自身将其设置为分离状态,则使用pthread_detach。 - 两种方法不能混用于同一个线程。 希望以上解释能够帮助你理解PTHREAD_CREATE_DETACHED和pthread_detach的使用。 §§相关问题§§ 1. 什么是POSIX线程(pthread)中的可连接(joinable)和分离(detached)线程? 2. 如何正确回收分离线程的资源? 3. 在多线程编程中,如何避免线程资源泄漏? 4. 除了分离线程,还有哪些线程同步和资源管理的方法? </think> ### PTHREAD_CREATE_DETACHED 与 pthread_detach 详解 #### 1. **基本概念** - **分离线程(Detached Thread)**:线程结束后自动释放资源,无需其他线程调用 `pthread_join` 回收资源。 - **可连接线程(Joinable Thread)**:必须由其他线程调用 `pthread_join` 回收资源,否则会导致资源泄漏。 #### 2. **两种分离方法对比** | **方法** | **使用场景** | **操作位置** | **返回值/错误码** | |----------------------------------|----------------------------------|-------------------|-------------------------------| | `PTHREAD_CREATE_DETACHED` (属性) | 创建线程时直接指定为分离状态 | 线程创建前(通过属性) | 成功返回0,失败返回错误码 | | `pthread_detach(thread_id)` | 创建后将可连接线程转为分离状态 | 线程创建后 | 成功返回0,失败返回错误码(如 `EINVAL`) | #### 3. **详细使用步骤** ##### (1) 创建时分离:`PTHREAD_CREATE_DETACHED` ```c #include <pthread.h> void* thread_func(void* arg) { // 线程任务代码 return NULL; } int main() { pthread_attr_t attr; pthread_t thread_id; // 初始化线程属性 pthread_attr_init(&attr); // 设置分离属性 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 创建分离线程 if (pthread_create(&thread_id, &attr, thread_func, NULL) != 0) { perror("线程创建失败"); } // 销毁属性对象 pthread_attr_destroy(&attr); return 0; } ``` **注意**: - 线程创建后**无需也不能**调用 `pthread_detach` 或 `pthread_join`,否则会触发错误(如 `EINVAL`)[^1]。 --- ##### (2) 创建后分离:`pthread_detach` ```c #include <pthread.h> void* thread_func(void* arg) { // 方法1:在线程内分离自身 pthread_detach(pthread_self()); // 线程任务代码 return NULL; } int main() { pthread_t thread_id; // 创建可连接线程 if (pthread_create(&thread_id, NULL, thread_func, NULL) != 0) { perror("线程创建失败"); } // 方法2:在主线程中分离 if (pthread_detach(thread_id) != 0) { perror("分离失败"); // 若线程已分离,返回 EINVAL } return 0; } ``` **关键点**: - 对同一个线程多次调用 `pthread_detach` 会返回 `EINVAL`(错误码22)[^1]。 - 若线程已通过属性设置为分离状态,再调用 `pthread_detach` 会报错[^3]。 --- #### 4. **常见错误与解决** - **错误场景**: ```c pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 设置分离属性 pthread_create(&thread_id, &attr, thread_func, NULL); pthread_detach(thread_id); // 错误!重复分离导致 EINVAL ``` - **原因**:线程已分离,再次分离违反操作规则[^3]。 - **解决**:**二选一**即可,禁止混用两种分离方式。 --- #### 5. **底层机制** - 线程属性 `PTHREAD_ATTR_FLAG_DETACHED` 标记分离状态[^3]。 - `pthread_detach()` 的内部逻辑: ```c if (线程已分离) return EINVAL; // 禁止重复分离 else 设置分离标志并释放资源; ``` --- #### 6. **最佳实践** 1. **优先使用 `PTHREAD_CREATE_DETACHED`** 适用于无需同步的场景(如后台任务)。 2. **动态分离用 `pthread_detach`** 当线程是否分离需运行时决定时使用。 3. **避免混用两种方法** 防止重复分离导致的 `EINVAL` 错误[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值