程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> “多線程”簡介及其C代碼實現框架

“多線程”簡介及其C代碼實現框架

編輯:關於C

在一些計算機專業相關的書籍中,大家經常聽說“多線程”這個概念。那麼什麼是“多線程”?什麼時候使用“多線程”?在程序設計中使用“多線程”有什麼好處呢?很多剛入職的程序員也對“多線程”感到非常的好奇,認為它很“高大上”。本文對“多線程”進行了簡單的介紹,並給出了其C代碼的實現框架。

“單線程”程序
要想理解“多線程”,那麼就要先從“單線程”說起。
大家都知道工廠“流水線”作業,裡面的工序是一環扣一環的,只有前面的一道工序完成之後,才能夠啟動下一道工序。這其實和“單線程”的原理非常的相似。
在“單線程”裡面,程序的功能是順序執行的,只有前面的流程都成功執行,後面的流程才能夠被執行到。例如,要實現一個話單文件生成、上傳和刪除的程序,使用“單線程”程序來完成,那麼其流程如圖1所示。
這裡寫圖片描述

圖1 “單線程”程序

“多線程”程序
大家也許注意到了,圖1中的生成文件、上傳文件和刪除文件的流程其實可以獨立開來。也就是說,這三個流程是互不影響的。這樣也就誕生了“多線程”的概念。
“多線程”,顧名思義,就是多個“單線程”,每個線程獨立地完成相關的功能。如圖1所示的程序,如果用“多線程”來實現,那麼其流程如圖2所示。
這裡寫圖片描述

圖2 “多線程”程序

從圖2可以看出,當程序啟動之後,線程1、線程2和線程3是同時運行的。線程1僅用於生成話單文件,線程2僅用於上傳話單文件,線程3僅用於刪除過期的話單文件。這樣一來,任何一個線程執行成功與否對另外兩個線程都沒有影響,真正地實現了程序的“並行”。

“多線程”的優點<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxiciAvPg0KJmxkcXVvO7bgz9+zzCZyZHF1bzvU2rTz0M3I7bz+s8zQ8tbQ09DXxbrcueO3urXE06bTw6OsxuTTxbXjyOfPwqO6PGJyIC8+DQq12tK7o6y9q9StwLTU2tK7uPa088H3s8zW0Mq1z9a1xLmmxNy3xbW9wcu24Lj20KHB97PM1tCjrLPM0PK4/LzTtcS88r3gus3S19Pa1MS2waGjPGJyIC8+DQq12rb+o6y9q7K7zay1xLmmxNy3xbW9srvNrLXEz9+zzNbQo6zM4bjfwcuzzNDytcTWtNDQ0KfCyqGjPGJyIC8+DQq12sj9o6wmbGRxdW87tuDP37PMJnJkcXVvO8q5tcOzzNDytcTEo7/pu6+4/Me/o6zT0MD709rXt9fZs8zQ8ta00NC5/bPMus3FxbLpzsrM4qGjPC9wPg0KPHA+PHN0cm9uZz4mbGRxdW87tuDP37PMJnJkcXVvO7XEQ7T6wuu/8rzcPC9zdHJvbmc+PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> /********************************************************************** * 版權所有 (C)2015, Zhou Zhaoxiong。 * * 文件名稱:ThreadCreate.c * 文件標識:無 * 內容摘要:演示多線程的創建 * 其它說明:無 * 當前版本:V1.0 * 作 者:Zhou Zhaoxiong * 完成日期:20151029 * **********************************************************************/ #include #include #include // 重定義數據類型 typedef signed int INT32; typedef unsigned int UINT32; // 宏定義 #define THREAD_NUM 5 // 線程個數 // 函數聲明 void ScanTask(void *pParam); void ProcessTask(void *pParam); /********************************************************************** * 功能描述:主函數 * 輸入參數:無 * 輸出參數:無 * 返 回 值:無 * 其它說明:無 * 修改日期 版本號 修改人 修改內容 * ------------------------------------------------------------------- * 20151029 V1.0 Zhou Zhaoxiong 創建 ***********************************************************************/ INT32 main() { pthread_t MultiHandle = 0; // 多線程句柄 pthread_t SingleHandle = 0; // 單線程句柄 UINT32 iLoopFlag = 0; INT32 iRetVal = 0; // 創建線程函數的返回值 // 循環創建線程 for (iLoopFlag = 0; iLoopFlag < THREAD_NUM; iLoopFlag ++) { iRetVal = pthread_create(&MultiHandle, NULL, (void * (*)(void *))(&ScanTask), (void *)iLoopFlag); if (0 != iRetVal) { printf(Create ScanTask %d failed! , iLoopFlag); return -1; } } // 單獨創建線程 iRetVal = pthread_create(&SingleHandle, NULL, (void * (*)(void *))(&ProcessTask), NULL); if (0 != iRetVal) { printf(Create ProcessTask failed! ); return -1; } return 0; } /********************************************************************** * 功能描述: 掃描線程 * 輸入參數: pParam-線程編號 * 輸出參數: 無 * 返 回 值: 無 * 其它說明: 無 * 修改日期 版本號 修改人 修改內容 * ---------------------------------------------------------------------- * 20151029 V1.0 Zhou Zhaoxiong 創建 ************************************************************************/ void ScanTask(void *pParam) { UINT32 iThreadNo = 0; // 線程編號 iThreadNo = (UINT32)pParam; // 獲取線程編號 printf(Now, into ScanTask[%d]. , iThreadNo); // 打印包含線程編號的消息 // 進行後續操作 } /********************************************************************** * 功能描述: 處理線程 * 輸入參數: 無 * 輸出參數: 無 * 返 回 值: 無 * 其它說明: 無 * 修改日期 版本號 修改人 修改內容 * ---------------------------------------------------------------------- * 20151029 V1.0 Zhou Zhaoxiong 創建 ************************************************************************/ void ProcessTask(void *pParam) { printf(Now, into ProcessTask. ); // 進行後續操作 }

說明
第一,本程序利用pthread_create函數來創建線程,該函數的原型是:

int pthread_create(pthread_t tidp,const pthread_attr_t *attr,(void)(start_rtn)(void),void *arg);

第一個參數為指向線程標識符的指針,在本程序中為MultiHandle和SingleHandle。
第二個參數用來設置線程屬性。
第三個參數是線程運行函數的起始地址,在本程序中即為函數名。
第四個參數是運行函數的參數,當同時創建多個功能相同的線程時,該參數表示線程編號。

第二,在Linux下,該程序的編譯命令為:gcc -g -o ThreadCreate ThreadCreate.c –lpthread。注意,最後的“–lpthread”是不能省略的,否則程序編譯不通過。因為pthread並非Linux系統的默認庫,而要在Linux中將其作為一個庫來使用,就需要加上“-lpthread”或“-pthread”以顯式鏈接該庫。
第三,在程序的多線程中,建議不要同時對同一個全局變量進行加、減等操作。如果確實需要這樣做,要注意在關鍵代碼處使用加鎖操作。

總結
隨著軟件功能的增強,隨之而來的就是程序復雜度的提升,這也使得程序從“單線程”到“多線程”的轉變成為必然。
“多線程”和“單線程”分別對應“並行”和“串行”,是軟件開發人員必須要掌握的一種程序設計的方法。設計合理的“多線程”程序不僅邏輯清晰、易於閱讀,而且程序的執行效率高,對於軟件產品效率和質量的提升具有很重要的意義。
最後,推薦大家閱讀一篇文章《進程與線程的一個簡單解釋》(http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html),本文以圖形的方式展示了進程與線程的區別,及有關操作系統的其它概念,值得一讀。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved