一、 线程
基本概念
线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。使用多线程主要是为了提高程序的执行效率和响应速度,因为线程之间可以共享进程的资源(如内存、文件句柄等),同时操作系统可以独立地调度线程的执行。
线程与进程的区别
-
地址空间: 进程拥有独立的地址空间,线程则共享进程的地址空间;
-
资源拥有: 进程拥有独立的资源,如内存空间、文件描述符等,而线程一般只拥有自己独立的栈(局部变量等)和线程控制块。
-
通信机制: 进程间通信(IPC)需要额外的通信机制,如管道、消息队列、共享内存等,而线程间通信相对简单,因为它们共享进程的内存空间。
-
系统开销: 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O设备等,所付出的开销远大于创建或撤销线程时的开销。
线程常用的应用场景
- 服务器应用:在多线程服务器中,每个线程可以处理一个客户端请求,从而提高服务器的并发处理能力。
- 并行计算:在并行计算中,可以利用多线程来充分利用多核处理器的计算能力,加速计算过程。
Linux下的线程
在Linux下,通常使用POSIX线程库(pthread)来创建和管理线程。在多线程程序中,为了防止数据竞争和确保线程间的有序执行,需要实现线程同步。Linux提供了多种同步机制,如互斥锁(mutexes)、条件变量(condition variables)、信号量(semaphores)等。
下面将详细介绍pthread线程库中常用的接口及示例
二、pthread线程库介绍
Linux下运行pthread,需包含头文件 <pthread.h> ,且通过gcc编译时,则需要链接pthread库,命令行如下:
gcc your_program.c -o your_program -lpthread
2.1 线程创建
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数介绍:
-
thread : 参数是一个输出型参数,用于获取创建成功的线程ID。
-
attr: 参数用于设置线程的属性,传入NULL表示使用默认属性。
-
start_routine:参数是一个函数地址,表示线程启动后要执行的函数。
-
arg:参数是传给线程例程的参数。
-
返回值: 线程创建成功返回0,失败则返回错误码。
2.2 线程等待
该函数是阻塞当前的线程,直到另外一个线程运行结束,是为了确保资源得到释放,避免系统泄露。
int pthread_join(pthread_t thread, void **retval);
参数介绍:
-
thread : 等待线程的ID。
-
retval: 存储线程的返回值的位置。
-
返回值: 线程等待成功返回0,失败返回错误码。
2.3 线程ID的获取
线程ID是一个无符号长整型数。
pthread_t pthread_self(void);
也可通过调用getppid();
和getpid();
获取当前进程的父进程ID(PPID)和当前进程ID【包含头文件
#include <unistd.h>
#include <sys/types.h>
2.4 线程的终止和退出
void pthread_exit(void *retval);
参数说明:
- retval:线程退出时的退出码信息。
功能: 该函数允许线程独立终止,而不影响其他线程或整个进程。线程可以通过调用 pthread_exit 提前结束自己的执行,并传递一个退出码。
2.5 取消线程
int pthread_cancel(pthread_t thread);
该函数用于取消指定线程,可在任何地方被取消
POSIX的取消类型有两种:
-
PTHREAD_CANCEL_DEFERRED :延时取消,即系统的默认类型,在线程到达取消点前,不会出现真正的取消;
-
PHREAD_CANCEL_ASYNCHRONOUS:异步取消,即线程可在任意时间取消。
三、示例
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
void* thread_func1(void* arg) {
int n = 5;
pthread_t id = pthread_self();
pid_t pid = getpid();
pid_t ppid = getppid();
while (n--) {
printf("线程消息:pid: %d, ppid:%d, thread1_id: %lu\n", pid, ppid, id);
sleep(1);
}
pthread_exit(NULL);
}
int main() {
pthread_t thread1;
if (pthread_create(&thread1, NULL, thread_func1, NULL) != 0) {
printf("创建线程失败\n");
return -1;
}
printf("主线程消息:pid: %d, ppid:%d, thread1_id: %lu\n", getpid(), getppid(), pthread_self());
pthread_join(thread1, NULL);
return 0;
}
编译命令行为:
gcc test.c -o test -lpthread
运行结果为:
上述为创建线程的简单示例,与线程相关的还有互斥锁mutex函数 、条件变量函数、信号量函数、共享内存函数等,则在后续的文章中持续更新。