概述
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运行单位。一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
相比于进程,线程是轻量级的实体,它们共享进程的资源(比如:内存地址空间等),因此创建和销毁线程的成本较低。因为线程共享相同的地址空间,所以它们之间的通信非常高效,不需要像进程间通信那样通过复杂的机制。
多线程的优势
多线程编程在现代计算环境中提供了显著的优势,尤其是在充分利用硬件资源、提高程序响应性和简化复杂任务处理方面。多线程的优势主要包括如下几点。
1、提高响应性。在一个多线程的应用中,即使一个线程正在等待I/O操作完成,其他线程仍然可以继续运行,从而保持应用程序的响应性。
2、充分利用CPU资源。现代计算机通常配备多个CPU核心。多线程允许一个应用程序同时在多个核心上运行不同的线程,从而充分利用硬件资源。比如:在视频编码软件中,每个帧的编码可以分配给不同的线程,以加速整个编码过程。
3、简化编程模型。对于一些复杂的问题(比如:矩阵运算或图像处理),可以将大任务分解为许多小任务,并分配给多个线程并行处理。这不仅提高了效率,还使得代码更易于理解和维护。
多线程的创建
在Linux中,创建多线程通常使用POSIX线程库pthreads。它是POSIX标准的一部分,旨在提供一个跨平台的多线程编程接口。
pthread_create函数用于创建一个新的线程,并允许我们指定新线程的属性、起始执行点以及传递给该执行点的参数。其函数原型如下。
cpp
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
各个参数和返回值的含义如下。
thread:用于存储新创建线程的标识符。
attr:用于设置新线程的属性,如栈大小、调度策略等。如果不需要特别配置线程属性,可以传递NULL使用默认属性。
start_routine:新线程开始执行时,调用的函数地址。这是一个函数指针,指向一个接受void*参数并返回void*的函数。这个函数是新线程的入口点,相当于主线程中的main函数。
arg:传递给start_routine函数的参数。它是一个通用指针类型,因此可以传递任何类型的单个参数。如果不需要传递参数,可以传递NULL。
返回值:0表示线程创建成功,其他值表示发生了错误。
多线程的等待
在Linux中,pthread_join函数用于等待指定的线程终止。它允许主线程或另一个线程暂停执行,直到目标线程完成其任务。这有助于确保线程间的正确同步,并且可以用来获取线程退出时的状态信息。其函数原型如下。
cpp
int pthread_join(pthread_t thread, void **retval);
各个参数和返回值的含义如下。
thread:目标线程的标识符,这是我们想要等待的线程。该参数必须是一个有效的、尚未被pthread_join等待过的线程ID。尝试对同一个线程多次调用pthread_join,或者对无效线程调用,会导致未定义行为。
retval:指向指针的指针,用于接收目标线程退出时返回的值。如果不关心线程的返回值,可以传递NULL。
返回值:0表示线程创建成功,其他值表示发生了错误。
实战代码
在下面的实战代码中,我们使用pthread_create和pthread_join来管理线程的生命周期,确保了主线程能够正确地与子线程同步,并且可以从子线程获取执行结果。
首先,我们定义了一个名为PrintMessage的函数作为新线程的入口点。该函数接收一个指向字符数组的指针作为参数,用于传递消息内容。
在函数内部,我们通过pthread_self获取并打印当前线程的ID,然后输出传入的消息字符串。接着,我们调用pthread_exit并传递一个字符串指针作为返回值,表示子线程已完成。
在main函数中,我们通过pthread_create函数创建子线程。如果创建失败,则输出错误信息并退出程序。创建成功后,主线程调用pthread_join等待子线程结束,并通过传递的指针pStatus获取子线程退出时的状态信息。最后,主线程打印出子线程的返回状态,并输出一条表示自身即将结束的消息。
cpp
#include <iostream>
#include <pthread.h>
using namespace std;
// 线程执行函数
void* PrintMessage(void* ptr)
{
char* pMsg = (char*)ptr;
cout << "Thread ID: " << pthread_self() << endl;
cout << "Message: " << pMsg << endl;
// 返回一个字符串作为状态
pthread_exit((void*)"Sub thread completed");
}
int main()
{
pthread_t thread;
const char* pMsg = "Hello from main thread";
// 创建线程
if (pthread_create(&thread, NULL, PrintMessage, (void*)pMsg))
{
cout << "Create thread failed" << endl;
return 1;
}
void* pStatus = NULL;
// 等待线程结束,并获取返回状态
if (pthread_join(thread, &pStatus))
{
cout << "Join thread failed" << endl;
return 2;
}
cout << "Sub thread returned: " << (char*)pStatus << endl;
cout << "Main thread exit" << endl;
return 0;
}