前言
本文分析的是llvm libc++的实现:http://libcxx.llvm.org/
class thread
thread类直接包装了一个pthread_t,在linux下实际是unsigned long int。
1 | class thread |
1 | id get_id() const _NOEXCEPT {return __t_;} |
用了一个std::unique_ptr来包装用户定义的线程函数:
创建线程用的是
1 | template <class _Fp> |
thread::joinable() , thread::join(), thread::detach()
再来看下thread::joinable() , thread::join(), thread::detach() 函数。
也是相应调用了posix的函数。在调用join()之后,会把_t设置为0,这样再调用joinable()时就会返回false。对于_t变量没有memory barrier同步,感觉可能会有问题。
1 | bool joinable() const {return __t_ != 0;} |
thread::hardware_concurrency()
thread::hardware_concurrency()函数,获取的是当前可用的processor的数量。
调用的是sysconf(_SC_NPROCESSORS_ONLN)函数,据man手册:
1 | - _SC_NPROCESSORS_ONLN |
1 | unsigned |
thread::sleep_for和thread::sleep_until
sleep_for函数实际调用的是nanosleep函数:
1 | void |
sleep_until函数用到了mutex, condition_variable, unique_lock,实际上调用的还是pthread_cond_timedwait函数:
1 | template <class _Clock, class _Duration> |
std::notify_all_at_thread_exit 的实现
先来看个例子,这个notify_all_at_thread_exit函数到底有什么用:
1 |
|
可以看到std::notify_all_at_thread_exit 函数,实际上是注册了一对condition_variable,mutex,当线程退出时,notify_all。
下面来看下具体的实现:
这个是通过Thread-specific Data来实现的,具体可以参考:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/
但我个人觉得这个应该叫线程特定数据比较好,因为它是可以被别的线程访问的,而不是某个线程”专有“的。
简而言之,std::thread在构造的时候,创建了一个__thread_struct_imp对象。
__thread_struct_imp对象里,用一个vector来保存了pair<condition_variable*, mutex*>
:
1 | class __thread_struct_imp |
当调用notify_all_at_thread_exit函数时,把condition_variable和mutex,push到vector里:
1 | void |
当线程退出时,会delete掉thread_struct_imp,也就是会调用thread_struct_imp的析构函数。
而在析构函数里,会调用历遍vector,unlock每个mutex,和调用condition_variable.notify_all()函数:
1 | __thread_struct_imp::~__thread_struct_imp() |
更详细的一些封闭代码,我提取出来放到了gist上:https://gist.github.com/hengyunabc/d48fbebdb9bddcdf05e9
其它的一些东东
关于线程的yield, detch, join,可以直接参考man文档:
1 | pthread_yield: |
总结
个人感觉像 join, detach这两个函数实际没多大用处。绝大部分情况下,线程创建之后,都应该detach掉。
像join这种同步机制不如换mutex等更好。
参考
- http://en.cppreference.com/w/cpp/thread/notify_all_at_thread_exit
- http://man7.org/linux/man-pages/man3/pthread_detach.3.html
- http://man7.org/linux/man-pages/man3/pthread_join.3.html
- http://stackoverflow.com/questions/19744250/c11-what-happens-to-a-detached-thread-when-main-exits
- http://man7.org/linux/man-pages/man3/pthread_yield.3.html
- http://man7.org/linux/man-pages/man2/sched_yield.2.html
- http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/
- man pthread_key_create