muduo学习笔记 - 第4章 C++多线程系统编程精要
第4章 C++多線程系統編程精要
-
Pthreads只保證統一進程之內,同一時刻的各個線程的id不同,不能保證同一進程先后多個進程具有不同的id,更不要說一臺機器上多個進程之間的id唯一性,pthread_t不適合用做程序對線程的標識符。
-
推薦使用**gettid()**的返回值作為線程id
- 返回值類型pid_t,通常是小整數,便于在日志輸出
- 可以在/proc文件系統中找到對應項,/proc/tid,/proc/pid/task/tid
- 任何時候全局唯一
- top判斷CPU占有最高的線程id
- pid = 0非法,系統的第一個進程init的pid = 1
4.1 線程的創建和銷毀應該遵循的原則
- 程序庫不應該在未提前告知的情況下創建自己的“背景線程”
- 盡量用相同的方式創建線程
- 在進入main()函數之前不應該啟動線程
- 程序中線程的創建最好能在初始化階段全部完成
4.2 線程的銷毀方式
- 自然死亡,從線程主函數返回,線程正常退出
- 非正常死亡,從縣城主函數拋出異常或線程觸發segfault信號等非法操作
- 自殺,在線程中調用pthread_exit()來立刻退出線程
- 他殺,其他線程調用pthread_cancel()來強制終止某個線程
線程正常退出的方式只有一種,自然死亡。強制終止線程的話,沒有機會清除所有的資源,也沒有機會釋放已經持有的鎖,其他線程如果對同一個mutex加鎖,那么他就會立刻死鎖。
如果程序中線程的創建能在初始化階段全部完成,線程是不必銷毀的,伴隨程序的一直運行,徹底避開了線程安全退出可能面臨的各種困難
4.3 exit在C++中不是線程安全的
exit()函數在C++中的作用除了終止進程,還會析構全局對象和已經構造完的函數靜態對象。這回潛在的死鎖可能
void someFunctionMayCallExit() {exit(1); } class GlobalObject { public:void doit() {MutexLockGuard lock(mutex_);someFunctionMayCallExit();}~GlobalObject() {printf("GlobalObject: ~GlobalObject\n");MutexLockGuard lock(mutex_); // 死鎖//clean upprintf("GlobalObject:~GlobalObject cleanning\n");} private:MutexLock mutex_; };GlobalObject g_obj; int main() {g_obj.doit(); }4.4 多線程與IO
-
多線程與IO可能存在的問題:
-
線程正在阻塞read()某個socket,另一個線程close()這個socket
-
線程正在阻塞的accept()某個listening socket,另一個線程close()這個socket
-
線程準備read()某個socket,另一個線程close()socket,第三個線程又open()了相同的fd的socket。POSIX標準要求每次新打開的文件使用當前最小的可用的文件描述符
-
-
為什么服務端程序不應該關閉標準輸出和標準出錯?
有些第三方庫會向stdout和stderr打印出錯信息,如果程序關閉了標準輸入和標準出錯,可能被網絡連接占用,造成對方收到莫名其妙的數據。正確的做法是把stdout和stderr重定向到磁盤文件
4.5 多線程與fork
fork()之后,子進程繼承了父進程的幾乎全部狀態,有些少數例外。子進程會繼承地址空間和文件描述符。
子進程不會繼承的有:
- 父進程的內存鎖,mlock,mlockall
- 父進程的文件鎖,fcntl
- 父進程的某些定時器,setitimer,alarm,timer_create
- 其他
fork()之后子進程只有一個線程,其他線程都消失了。這可能存在隱患:一些線程持有鎖處于臨界區,而子線程試圖對同一個mutex加鎖,這會造成死鎖。
fork()之后,子進程不能調用:
- malloc,malloc在訪問全局狀態時,幾乎肯定會加鎖
- 任何可能分配或釋放內存的函數,new,map::insert(),snprintf
- 任何pthread函數
- printf函數,其他線程可能恰好持有stdout/stderr鎖
- 除了signal安全函數之外的任何函數
唯一安全的做法是在fork()之后立即調用exec()執行另一個程序,徹底隔斷子進程與父進程的聯系
總結
以上是生活随笔為你收集整理的muduo学习笔记 - 第4章 C++多线程系统编程精要的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: muduo学习笔记 - 第3章 多线程服
- 下一篇: C++堆 和 栈 空间的区别