?

淺談linux多線程協作

2017-03-09 15:48史歡歡周光森姚永哲
環球市場 2017年36期
關鍵詞:調用線程隊列

史歡歡 周光森 姚永哲

沈陽中鈔信達金融設備有限公司

1、線程的創建和終止

1)在線程創建之前,需要初始化線程,設置線程的優先級、是否繼承父進程優先級、調度策略,并分配各個線程的優先級。創建線程的函數是pthread_create()。

2)線程的終止的兩種方式:第一通過return從線程函數返回,第二種通過調用pthread_exit()函數使線程退出。此外,主線程中如果從main函數返回或是調用了exit函數退出主線程,則整個進程終止,此時所有的其他線程也將終止。另一種是,如果主線程調用pthread_exit函數,則僅僅是主線程消亡,進程不會結束,其他線程也不會結束,直到所有的線程都結束時,進程才結束。

2、多線程協作

線程與線程之間通訊,互相交互變量,不能總用全局變量,這樣會出現A線程正在改全局變量的值,B線程卻在讀全局變量的值,因為各線程是并行工作,所以需要加互斥鎖、條件變量或消息隊列來同步。

1)互斥鎖pthread_mutex_lock(unlock或trylock):用來防止兩個進程或線程在同一時刻訪問相同的共享資源。如果互斥量已經上鎖,調用線程會阻塞,直到互斥量被解鎖。比如A和B兩個線程都要用a變量,在A線程中,加鎖之后改變a變量的值,然后解鎖,而在B線程中,加鎖之后讀a變量的值,然后解鎖,加鎖和解鎖必須判斷是否成功,否則對a變量的讀寫會出錯,最好用pthread_mutex_trylock加鎖,如果加鎖失敗,會返回EBUSY,成功則返回0,返回EBUSY說明另一線程對這個變量加鎖后還未解鎖。此外,阻塞和非阻塞的意思是,阻塞是一直加鎖直到成功,非阻塞是加鎖完畢后不管成功與否都返回。

2)條件變量cond

條件變量的基本操作是當觸發條件(當條件變為真時),等待條件,掛起線程直到其他線程觸發條件。即A線程先進入wait等待,讓其掛起,等待B線程執行激活后,A線程繼續執行。為了防止競爭,條件變量總是和一個互斥鎖結合在一起。pthread_cond_wait一般嵌套在while(條件)中,條件第一次滿足就可以。激活等待線程是激發條件有兩種形式,pthread_cond_signal( )激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個;而pthread_cond_broadcast()則激活所有等待線程。

3)消息隊列:在A線程中改變某個變量后,發消息給B線程,B線程在沒有得到消息時處于掛起狀態,除非A線程給B線程發消息,B線程接收到消息才開始執行msgrcv的下一行代碼。msgsnd向隊列末端添加一條新消息;msgrcv從隊列中取消息,取消息是不一定遵循先進先出的,也可以按消息的類型字段取消息;

4)線程之間是異步的,無法確定哪個線程先執行。如果在同一優先級中有N個線程,需要使用sleep來調整各個線程執行的順序。

5)Linux下多個線程同時對一個文件進行寫操作,需要使用文件鎖解決沖突,使用int flock(int fd,int operation)(鎖定文件或解除鎖定)函數。flock()會依參數operation所指定的方式對參數fd所指的文件做各種鎖定或解除鎖定的動作。此函數只能鎖定整個文件,無法鎖定文件的某一區域。LOCK_EX 建立互斥鎖定,一個文件同時只有一個互斥鎖定。LOCK_NB 無法建立鎖定時,此操作可不被阻斷,馬上返回進程。通常與LOCK_EX 做OR(|)組合。

if(flock(fileno(文件指針),LOCK_EX | LOCK_NB)== FAILURE)//文件加鎖

if(flock(fileno(文件指針),LOCK_UN)== FAILURE)//釋放文件鎖

3、線程內部處理

1)線程中程序不運行的三種狀態睡眠sleep()、阻塞、掛起,他們的區別是:

①掛起:沒有滿足的運行條件,正在待命,比如msgrcv,沒有接收到消息時就掛起,讓別的線程執行,自己等待msgsnd,一旦接收到消息,繼續執行;

②sleep( ):歇一會,讓別的線程先運行;

③阻塞:線程由于等待處理器外的其他條件無法運行,如條件變量的改變、加鎖互斥量或I/O操作結束。

2)單線程進入死循環

如果線程中所有程序的執行需要滿足if條件,但if條件一直不滿足,這個線程將處于死循環,使別的線程也無法執行??梢栽趇f之后加入else,里面是sleep(),在執行sleep()期間,別的線程就可以運行。

3)線程定時執行

如果想讓在線程定時執行某個函數,需要用到setitimer()有兩個功能,一是指定一段時間后,才執行某個function,二是每間隔一段時間就執行某個function。如果要實現間隔執行,程序中一定要加pause( )函數,并且嵌套在while(1)中。

結束語:

在應用軟件中編寫各個線程的程序。調用linux中的系統函數一定要接收返回值來判斷是否執行成功。linux程序不能實時仿真,調試程序只能通過printf打印變量值到串口。所以在寫linux程序,一定要防止內存泄漏,比如數組、變量類型、指針一定要推敲使用。遇到內存泄漏,用printf來打印定位。

猜你喜歡
調用線程隊列
基于C#線程實驗探究
隊列里的小秘密
基于多隊列切換的SDN擁塞控制*
基于國產化環境的線程池模型研究與實現
核電項目物項調用管理的應用研究
線程池調度對服務器性能影響的研究*
在隊列里
豐田加速駛入自動駕駛隊列
基于系統調用的惡意軟件檢測技術研究
利用RFC技術實現SAP系統接口通信
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合