linux多线程之线程基础
目录
1. 线程创建函数 pthread_create
2. 线程等待函数 pthread_join
3. 线程终止函数 pthread_exit
4. 线程取消函数 pthread_cancel(简单了解即可)
5. 线程属性相关函数(简单了解即可)
代码示例
在 Linux 系统中,使用 POSIX 线程库(pthread)进行多线程编程时,涉及多个关键函数。以下详细讲解这些函数:
1. 线程创建函数 pthread_create
- 函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
- 功能:创建一个新的线程。新线程从
start_routine
函数开始执行。 - 参数:
thread
:指向pthread_t
类型变量的指针,该变量将被函数填充为新创建线程的标识符。通过这个标识符,可以对特定线程进行后续操作,如等待线程结束、取消线程等。attr
:用于指定线程的属性,如栈大小、调度策略等。如果设置为NULL
,则使用默认的线程属性。例如,若要自定义线程栈大小,可以先初始化一个pthread_attr_t
结构体,通过pthread_attr_setstacksize
等函数设置相关属性,再将其作为参数传递给pthread_create
。start_routine
:指向线程函数的指针。这个函数是新线程的执行入口,其原型必须为void* function_name(void* arg)
。arg
:传递给start_routine
函数的参数。它以void*
类型传递,可以是任何类型的数据指针。如果不需要传递参数,可设为NULL
。
- 返回值:成功时返回
0
,失败时返回非零错误码,如EAGAIN
(系统资源不足,无法创建新线程)、EINVAL
(无效的线程属性)等。通过这些错误码,可以判断线程创建失败的原因并进行相应处理。
2. 线程等待函数 pthread_join
- 函数原型:
int pthread_join(pthread_t thread, void **retval);
- 功能:调用该函数的线程(通常为主线程)会阻塞,直到指定的线程
thread
执行完毕。它用于回收指定线程的资源,防止线程成为 “僵尸线程”。 - 参数:
thread
:要等待结束的线程的标识符,即之前通过pthread_create
创建线程时填充的pthread_t
变量。retval
:用于获取被等待线程的返回值。如果不关心线程的返回值,可以将其设置为NULL
。若线程函数通过pthread_exit
或return
返回了一个非NULL
的指针,pthread_join
会将该指针存储在retval
指向的位置。
- 返回值:成功时返回
0
,失败时返回非零错误码,如EINVAL
(无效的线程标识符)、ESRCH
(没有找到对应的线程)等。
3. 线程终止函数 pthread_exit
- 函数原型:
void pthread_exit(void *retval);
- 功能:用于终止调用它的线程。线程执行到
pthread_exit
后,会立即停止执行,并将控制权返回给系统。同时,该线程所占用的资源(除了栈空间)会被释放。 - 参数:
retval
是线程的返回值,可被pthread_join
获取。如果线程不需要返回值,可以将retval
设置为NULL
。 - 注意:如果在主线程中调用
pthread_exit
,主线程会终止,但其他线程仍会继续执行。这与使用exit
函数不同,exit
会终止整个进程,包括所有线程。
4. 线程取消函数 pthread_cancel(简单了解即可)
- 函数原型:
int pthread_cancel(pthread_t thread);
- 功能:请求取消指定的线程
thread
。被请求取消的线程不一定会立即终止,它会在遇到 “取消点” 时才会真正处理取消请求并终止。 - 参数:
thread
为要取消的线程的标识符。 - 返回值:成功时返回
0
,失败时返回非零错误码,如EINVAL
(无效的线程标识符)。 - 取消点:POSIX 标准定义了一些函数为取消点,如
pthread_join
、pthread_testcancel
、sleep
、read
、write
等。当线程执行到这些函数时,如果收到取消请求,会按照一定规则处理取消操作。线程也可以通过pthread_setcancelstate
和pthread_setcanceltype
函数来设置自身对取消请求的处理方式,如是否允许取消、是异步取消还是延迟取消等。
5. 线程属性相关函数(简单了解即可)
- 初始化线程属性函数
pthread_attr_init
:- 函数原型:
int pthread_attr_init(pthread_attr_t *attr);
- 功能:初始化一个线程属性对象
attr
,使其处于默认状态。在使用自定义线程属性前,必须先调用此函数进行初始化。 - 返回值:成功时返回
0
,失败时返回非零错误码。
- 函数原型:
- 销毁线程属性函数
pthread_attr_destroy
:- 函数原型:
int pthread_attr_destroy(pthread_attr_t *attr);
- 功能:销毁一个线程属性对象,释放与之相关的资源。在不再需要使用线程属性对象时,应调用此函数进行清理。注意,如果该属性对象已被用于创建线程,调用此函数可能会导致未定义行为。
- 返回值:成功时返回
0
,失败时返回非零错误码。
- 函数原型:
- 设置线程栈大小函数
pthread_attr_setstacksize
:- 函数原型:
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
- 功能:设置线程属性对象
attr
中指定的线程栈大小为stacksize
字节。通过调整栈大小,可以满足不同线程对栈空间的需求,例如某些递归深度较大的线程可能需要更大的栈空间。 - 返回值:成功时返回
0
,失败时返回非零错误码。
- 函数原型:
- 获取线程栈大小函数
pthread_attr_getstacksize
:- 函数原型:
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
- 功能:获取线程属性对象
attr
中设置的线程栈大小,并将其存储在stacksize
指向的变量中。 - 返回值:成功时返回
0
,失败时返回非零错误码。
- 函数原型:
代码示例
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>// 线程函数
void* print_message(void* msg) {const char* message = (const char*)msg;printf("%s\n", message);return NULL;
}int main() {pthread_t threads[3];const char* messages[3] = {"Thread 1 says Hello!","Thread 2 says Hi!","Thread 3 says Greetings!"};int i, rc;// 创建线程for (i = 0; i < 3; i++) {printf("Creating thread %d\n", i);rc = pthread_create(&threads[i], NULL, print_message, (void*)messages[i]);if (rc) {printf("ERROR; return code from pthread_create() is %d\n", rc);exit(-1);}}// 等待所有线程完成for (i = 0; i < 3; i++) {pthread_join(threads[i], NULL);}printf("All threads completed.\n");return 0;
}