task_struct
内核数据结构对象,但是进程地址空间是共享的,因此可以认为,同一个进程中的多个线程共享所有的代码和数据,线程间天然可通信,具有较高的耦合度cache
的内部数据(通常是一些指令数据)和进程页表无须换出,只需要切换一些寄存器中的执行流上下文信息即可,因此线程间调度切换比进程间调度切换的效率要高很多,同时线程占用的系统资源也较少,多线程可以有效提高系统的并发量和运行效率(尤其是在有多个执行流调度队列的多核CPU中)POSIX
第三方线程库(动态库),Linux环境下编写多线程代码需要调用该库进行线程的创建和维护管理POSIX
线程库统一维护在struct pthread
结构体中,通过动态库链接的方式,映射到进程地址空间的共享区段(用户本质上也可以自己通过系统调用接口自己维护线程栈和局部存储变量,但是比较麻烦,因此有人开发了线程库)pthread_create
,线程被创建后,其执行流会立即调用指定函数,主线程通过接口pthread_join
对其他线程进行阻塞等待以获取执行结果#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <stdio.h>
#include <string>
//任务请求对象
class Request
{
public:
Request(int start, int end, const std :: string &threadname)
: start_(start), end_(end), threadname_(threadname)
{}
public:
int start_;
int end_;
std :: string threadname_;
};
//请求回应对象
class Response
{
public:
Response(int result, int exitcode)
:result_(result),
exitcode_(exitcode)
{}
public:
int result_; // 计算结果
int exitcode_; // 计算结果是否可靠
};
//线程的执行流代码
void * SumThread(void * args){
Request * Task = static_cast<Request *>(args);
Response * Res = new Response(0,0);
int begin = Task->start_;
int end = Task->end_;
for(int i = begin ; i <= end ; ++i){
std :: cout << Task->threadname_ << " is runing, Summing..., " << i << std :: endl;
Res->result_ += i;
usleep(100000);
}
//注意使用完请求后释放请求结构体,防止内存泄漏
delete Task;
return static_cast<void *>(Res);
}
int main()
{
pthread_t tid;
Request *rq = new Request(1, 100, "thread 1");
//创建线程并传递计算任务请求
pthread_create(&tid, nullptr, SumThread, rq);
//用于接收Respond结构体地址
void *ret;
//pthread_join接口的ret参数用于获取线程函数的返回值,pthread_join接口默认执行阻塞等待
pthread_join(tid, &ret);
Response *rsp = static_cast<Response *>(ret);
std :: cout << "rsp->result: " << rsp->result_ << ", exitcode: " << rsp->exitcode_ << std :: endl;
delete rsp;
return 0;
}