muduo库源码分析(4):线程类
来源:互联网 发布:云计算前景分析 编辑:程序博客网 时间:2024/06/05 07:20
- 与muduo线程类封装有关的源文件:
Thread.cc Thread.h CurrentThread.h - muduo线程类封装实现方式:
基于对象的编程(利用boost::function/boost::bind实现) - 简化版的线程类封装可参考:
http://blog.csdn.net/jacktangj/article/details/76166554 - muduo线程类整体结构:
这里简化了成员函数以及全局函数
Thread类:线程类
CurrentThread命名空间:声明每个线程的私有数据
ThreadNameInitializer 类:用于初始化主线程的线程特有数据
ThreadData结构体:通过回调函数传递给子线程的数据
简单分析Thread类的运行过程。
- detail命名空间有全局变量init,会首先调用ThreadNameInitializer 类构造函数。以及包含静态成员numCreate_(原子类Automic)的初始化
ThreadNameInitializer 类结构
class ThreadNameInitializer{ public: ThreadNameInitializer() { muduo::CurrentThread::t_threadName = "main"; CurrentThread::tid(); pthread_atfork(NULL, NULL, &afterFork); }};1.__thread int t_cachedTid;//线程实际ID的缓存,减少多次调用syscall(SYS_gettid)获取线程实际ID __thread char t_tidString[32];//线程tid的字符串形式 __thread int t_tidStringLength;//线程tid的字符串形式的长度 __thread const char* t_threadName;// 线程的名字 __thread修饰的变量为每个线程的私有数据,不共享 只能修饰POD类型数据(后面注意2),非POD数据可用线程的特定数据实现2. inline int tid(){ if (__builtin_expect(t_cachedTid == 0, 0)) { cacheTid(); } return t_cachedTid;}__builtin_expect:gcc的编译优化语句,用于提前加载if的语句还是else语句void CurrentThread::cacheTid(){ if (t_cachedTid == 0) { t_cachedTid = detail::gettid(); t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid); }}pid_t gettid(){ return static_cast<pid_t>(::syscall(SYS_gettid));}syscall(SYS_gettid)//获取线程的实际ID(后面注意1)3.pthread_atfork(prepare,parent,child)在fork之前执行prepare函数,fork后主进程执行parent,子进程执行child注意:多线程程序最好不要去fork,很容易造成死锁
2.构造Thread类的构造函数(Thread t(threadFunc);)
Thread::Thread(const ThreadFunc& func, const string& n) : started_(false),//标记线程是否启动 joined_(false),// 标记线程是否连接,即pthread_join pthreadId_(0),// 线程ID tid_(new pid_t(0)),// 线程实际ID func_(func),// 回调函数 name_(n)// 线程名{ setDefaultName();}void Thread::setDefaultName(){// 静态成员变量用于线程计数:原子性操作+1 int num = numCreated_.incrementAndGet(); if (name_.empty()) { char buf[32]; snprintf(buf, sizeof buf, "Thread%d", num); name_ = buf; }}
3.执行(t.start();t.join();)
void Thread::start(){ assert(!started_); started_ = true; detail::ThreadData* data = new detail::ThreadData(func_, name_, tid_); // 创建线程 if (pthread_create(&pthreadId_, NULL, &detail::startThread, data)) { started_ = false; delete data; // or no delete? LOG_SYSFATAL << "Failed in pthread_create";//日志文件输出(后续) }}void* startThread(void* obj){ ThreadData* data = static_cast<ThreadData*>(obj); data->runInThread(); delete data; return NULL;}
注意:
1.线程标识符:
进程———-线程
pid_t———-pthread_t
getpid()———-pthread_self()
标识符唯一———-不同进程拥有相同线程ID
linux中posix线程实现也是一个轻量级进程,只是该进程与主进程共享一些资源,有时需要实际的线程ID,例如p1->p2某个线程时,既不能用p2的pid也不能用改线程的pthread_self(),只能用线程的实际ID,获取方式调用:syscall(SYS_gettid)
2.POD类型:与C兼容的数据类型(int,double,结构体等),但用户定义的带有构造函数和虚函数的类则不是。
阅读全文
0 0
- muduo库源码分析(4):线程类
- Muduo库源码分析(7):线程池
- Muduo库源码分析(9):线程特定数据
- muduo源码分析:线程类Thread封装
- muduo源码分析:线程池类ThreadPool
- muduo库源码分析
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- muduo源码分析:线程特定/私有数据类ThreadLocal
- muduo库源码分析(3):异常类
- Muduo库源码分析(5):互斥锁,条件变量类
- muduo源码分析(1):时间类
- muduo源码分析--buffer中的线程安全
- muduo源码分析之多线程TcpServer
- muduo源码分析--线程池的实现
- muduo源码分析---EventLoop类
- muduo源码分析--EventLoopThreadPool类
- muduo源码分析:ThreadLocalSigleton类
- Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数
- Calendar
- 1078. Hashing (25)哈希二次碰撞探测
- Java标识符,注释,数据类型,变量,常量,数据类型转换
- Bigdecimal
- MVC,MVP优缺点总结
- muduo库源码分析(4):线程类
- 编程之路的起跑线
- 排序
- docker搭建redis集群
- 一般直流电机与直流伺服电机的区别:
- 2.回看JAVA之数据类型
- POJ2411 Mondriaan's Dream (轮廓线动态规划典型例题 以及用状态压缩逐行深搜推的方法)
- 仿造QQ登陆框自定义密码输入框
- dwz查询找回