如何理解C++11中的多线程(了解)
#include <iostream>
#include <unistd.h>
#include <thread>
void thread_run()
{
while (true)
{
std::cout << "我是新线程..." << std::endl;
sleep(1);
}
}
int main()
{
// 任何语言需要在Linux上实现多线程,必定是要用到pthread库的!
// 如何看待C++11中的多线程呢?
// 本质上就是对pthread库的封装
std::thread t1(thread_run);
while (true)
{
std::cout << "我是主线程..." << std::endl;
sleep(1);
}
t1.join();
return 0;
}
封装代码
封装代码写在Thread.hpp 文件当中,未来想使用封装好的线程就直接包含Thread.hpp文件即可!
// hpp 表示header only 开源代码
// 将函数定义和声明放在一起
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include <cassert>
// 先声明 要使用
class Thread;
// 上下文,当大号结构体使用
// 用Context来处理静态方法调用不了成员变量的问题
class Context
{
public:
Thread *this_;
void *args_;
public:
Context() : this_(nullptr), args_(nullptr)
{}
~Context()
{}
};
// 对线程做封装,以后就不需要总去调用原生库的接口了
class Thread
{
public:
// using func_t = std::function<void*(void*)>; -- C++11 智能指针
typedef std::function<void *(void *)> func_t;
const int num = 1024;
// "void *(Thread::*)(void *args)" 类型的实参与 "void *(*)(void *)" 类型的形参不兼容C/C++(167) -- 报错
// 为啥呢? -- 因为start_routine是类内的成员函数,有缺省参数this指针
// void* start_routine(void* args)
// {
// return func_(args);
// }
// 在类内创建线程 这样就没有this指针了
static void *start_routine(void *args)
{
// 但是没有this指针
// 静态方法不能调用成员方法或成员变量
// return func_(args);
// 可以采用友元,或者public成员的方式 这里不用!!
// 将args强转成Context的指针
Context *ctx = static_cast<Context*>(args);
// 调用run方法 -- 将方法从静态中剥离出来
void* ret = ctx->this_->run(ctx->args_);
delete ctx;
return ret;
}
// 构造函数
Thread(func_t func, void *args = nullptr, int number = 0) : func_(func), args_(args)
{
char buffer[num];
snprintf(buffer, sizeof buffer, "thread-%d", number);
name_ = buffer;
// 加上Context
Context* ctx = new Context();
ctx->this_ = this;
ctx->args_ = args_;
// 将ctx传过去
int n = pthread_create(&tid_, nullptr, start_routine, ctx);
//int n = pthread_create(&tid_, nullptr, start_routine, args);
assert(n == 0);
(void)n;
}
// 线程等待
void join()
{
int n = pthread_join(tid_, nullptr);
assert(n == 0);
(void)n;
}
void *run(void *args)
{
return func_(args);
}
// 析构
~Thread()
{
// do nothing
}
private:
// 自定义线程名 方便观察(不需要通过观察tid)
// 末尾加_ 将成员变量和参数做区分
std::string name_;
pthread_t tid_;
// 线程执行任务
func_t func_;
// 获取参数
void *args_;
};
使用封装
#include "Thread.hpp"
#include <memory>
#include <unistd.h>
void *thread_run(void *args)
{
std::string work_type = static_cast<const char *>(args);
while (true)
{
std::cout << "我是一个新线程,我正在做:" << work_type << std::endl;
sleep(1);
}
}
int main()
{
std::unique_ptr<Thread> thread1(new Thread(thread_run, (void *)"hellothread", 1));
std::unique_ptr<Thread> thread2(new Thread(thread_run, (void *)"countthread", 2));
std::unique_ptr<Thread> thread3(new Thread(thread_run, (void *)"printthread", 3));
std::unique_ptr<Thread> thread4(new Thread(thread_run, (void *)"iothread", 4));
thread1->join();
thread2->join();
thread3->join();
thread4->join();
return 0;
}