多線程程序中,線程安全是必須要考慮的因素。C語言中大部分函庫函數都是線程安全的,但是也有幾個常用函數是線程不安全的,也叫不可重入函數。
線程不安全函數原因淺析
之所線程不安全,是因為這些係統函數使用了某些全局或者靜態變量。我們知道,全局變量和靜態變量分別對應內存中的全局變量區和靜態存儲區,這些區域都是可以跨函數跨線程訪問的。一旦在多線程環境中使用,在沒有加鎖的情況下,對同一段內存塊進行並發讀寫,就會造成segmentfault/coredump之類的問題。關於LINUX內存區域的分析詳見:剖析程序的內存布局。
常見的線程不安全類型有兩類:
- 函數依賴了全局變量,並且會修改全局變量,如
rand()
的實現每次調用都會修改和讀取一個全局的INT。 - 函數返回了靜態變量,如
ctime()
函數。
C語言不可重入函數匯總
這裏匯總了C語言中常見的不可重入函數,並提供了對應的線程安全版本。如果確實需要在多線程中使用這些函數,務必要改成帶”_r”的線程安全版本。
線程不安全函數 | 函數說明 | 線程不安全類型 | unix線程安全版本 |
---|---|---|---|
rand | 產生隨機整數 | 1 | rand_r |
strtok | 字符串split | 1 | strtok_r |
asctime | asc時間 | 2 | asctime_r |
ctime | 時間戳 | 2 | ctime_r |
gethostbyaddr | 返回主機信息 | 2 | gethostbyaddr_r |
gethostbyname | 返回主機信息 | 2 | gethostbyname_r |
inet_ntoa | 轉成IP | 2 | 暫無 |
localtime | 返回本地時間 | 2 | localtime_r |
C語言常用的多線程庫
C語言中常用的多線程庫一般是pthread, 當然也可以使用GLIB中的gthread, 上述的線程安全版本可以兼容這兩個庫開發的多線程程序。