【四】线程
1. 线程的创建
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
-
pthread_t *thread
:指向线程标识符的指针,用于存储新创建线程的 ID。 -
const pthread_attr_t *attr
:线程属性指针,通常传NULL
使用默认属性。 -
void *(*routine)(void *)
:线程执行的函数指针,即线程开始执行的函数。 -
void *arg
:传递给线程函数的参数,可以是任意类型,但需要正确转换。
返回值
-
成功:返回 0。
-
失败:返回非零错误码。
特点
-
创建线程需要时间,如果主进程很快退出,线程可能无法执行。
-
主进程退出时,其创建的所有线程也会随之退出。
示例代码
#include <stdio.h> #include <pthread.h> #include <unistd.h> // 线程执行函数 void *thread_function(void *arg) { printf("Thread is running, TID: %lu\n", pthread_self()); sleep(2); printf("Thread finished\n"); return NULL; } int main() { pthread_t tid; int ret = pthread_create(&tid, NULL, thread_function, NULL); if (ret != 0) { perror("pthread_create failed"); return 1; } printf("Main process, PID: %d\n", getpid()); sleep(3); // 确保线程有时间运行 return 0; }
2. 线程的退出
pthread_exit
#include <pthread.h> void pthread_exit(void *retval);
-
void *retval
:线程的返回值,可以是任意类型,但需要正确转换。
特点
-
调用
pthread_exit
可以使线程正常退出。 -
主进程退出时,其创建的所有线程也会随之退出。
示例代码
#include <stdio.h> #include <pthread.h> // 线程执行函数 void *thread_function(void *arg) { printf("Thread is running, TID: %lu\n", pthread_self()); sleep(2); printf("Thread finished\n"); pthread_exit((void *)0); // 线程正常退出 return NULL; } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_function, NULL); printf("Main process, waiting for thread...\n"); sleep(3); return 0; }
3. 获取线程 ID
pthread_self
#include <pthread.h> pthread_t pthread_self(void);
特点
-
返回当前线程的 ID。
-
可以通过
pthread_create
的第一个参数获取线程 ID,也可以在线程内部调用pthread_self
获取。
示例代码
#include <stdio.h> #include <pthread.h> // 线程执行函数 void *thread_function(void *arg) { printf("Thread is running, TID: %lu\n", pthread_self()); return NULL; } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_function, NULL); printf("Main process, PID: %d\n", getpid()); sleep(1); return 0; }
4. 线程间参数传递
参数传递方式
pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*routine)(void *), void *arg);
-
通过地址传递参数:注意类型的转换。
-
值传递:编译器可能会告警,需要程序员自己保证数据长度正确。
示例代码
#include <stdio.h> #include <pthread.h> #include <stdlib.h> // 线程执行函数 void *thread_function(void *arg) { int num = *((int *)arg); // 转换为 int 类型 printf("Thread is running, received number: %d\n", num); free(arg); // 释放分配的内存 return NULL; } int main() { pthread_t tid; int *num = (int *)malloc(sizeof(int)); *num = 42; pthread_create(&tid, NULL, thread_function, (void *)num); printf("Main process, sent number: %d\n", *num); sleep(1); return 0; }
5. 线程的回收
pthread_join
#include <pthread.h> int pthread_join(pthread_t thread, void **retval);
-
pthread_t thread
:要回收的线程 ID。 -
`void retval
**:用于存储线程的返回值,可以是
NULL`。
返回值
-
成功:返回 0。
-
失败:返回非零错误码。
特点
-
pthread_join
是阻塞函数,如果回收的线程未结束,则一直等待。
示例代码
#include <stdio.h> #include <pthread.h> // 线程执行函数 void *thread_function(void *arg) { printf("Thread is running, TID: %lu\n", pthread_self()); sleep(2); printf("Thread finished\n"); return (void *)0; } int main() { pthread_t tid; void *retval; pthread_create(&tid, NULL, thread_function, NULL); printf("Main process, waiting for thread...\n"); int ret = pthread_join(tid, &retval); if (ret != 0) { perror("pthread_join failed"); return 1; } printf("Thread exited with status: %ld\n", (long)retval); return 0; }
6. 线程的分离
1、使用 pthread_detach
#include <pthread.h> int pthread_detach(pthread_t thread);
2、创建线程时设置分离属性
#include <pthread.h> pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
特点
-
分离线程在退出时会自动回收资源,无需显式调用
pthread_join
。
示例代码
#include <stdio.h> #include <pthread.h> // 线程执行函数 void *thread_function(void *arg) { printf("Thread is running, TID: %lu\n", pthread_self()); sleep(2); printf("Thread finished\n"); return NULL; } int main() { pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&tid, &attr, thread_function, NULL); printf("Main process, PID: %d\n", getpid()); sleep(3); return 0; }
-
查看线程
ps -eLf | grep [名字]