程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 一起talk C栗子吧(第一百一十六回:C語言實例--線程同步之互斥量二)

一起talk C栗子吧(第一百一十六回:C語言實例--線程同步之互斥量二)

編輯:關於C語言

一起talk C栗子吧(第一百一十六回:C語言實例--線程同步之互斥量二)



各位看官們,大家好,上一回中咱們說的是線程同步之信號量的例子,這一回咱們繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!

我們在上一回中詳細介紹了互斥量相關函數的用法,這一回中,我們介紹如何使用這些函數來操作互斥量。

下面是詳細的操作步驟:

1.定義一個互斥量A,用來同步線程; 2.在創建線程的進程中使用pthread_mutex_init函數初始化互斥量,互斥量的屬性使用默認值; 3.在讀取數據的線程中讀取數據,首先使用pthread_mutex_lock函數對互斥量A進行加鎖操作;然後讀取數據,最後使用pthread_mutex_unlock函數對互斥量A進行解鎖操作; 4.在第寫數據的線程中修改數據,首先使用pthread_mutex_lock函數對互斥量A進行加鎖操作;然後修改數據,最後使用pthread_mutex_unlock函數對互斥量A進行解鎖操作; 5.在創建線程的進程中使用pthread_mutex_destroy函數釋放互斥量相關的資源;

看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以下載使用。

我們寫的代碼是在信號量互斥代碼的基礎上修改而來的,不過我們在代碼中使用互斥量代替了信號量。代碼中了讀/寫數據的函數是自己實現的,目的是為了方便說明問題,在這兩個函數中都使用了延時操作,目的是為了說明讀或者寫數據需要一定的時間。

在程序運行時可能會存在這樣的情況:

讀操作還沒有完成,就開始寫操作,這樣會造成讀操作讀取的數據不准確; 寫操作還沒有完成,就開始讀操作,這樣會造成讀操作讀取的數據不准確;

下面是沒有使用互斥量時程序的運行結果,請大家參考:

Create first thread         //創建第一個線程
Create second thread        //創建第二個線程
Thread ID::3076062016 -----------S---------- 
[Thread_1] start reading data     //第一個線程開始讀取數據(對數據的第一個操作是讀操作)
Thread ID::3067669312 -----------S---------- 
[Thread_2] start writing data     //第二個線程開始修改數據
[Thread_1] data = 0               //第一個線程讀取到的是共享數據的初始值
[Thread_1] end reading data 
[Thread_2] data = 1               //第二個線程對共享數據進行修改
[Thread_2] end writing data 
[Thread_2] start writing data     
[Thread_1] start reading data     
[Thread_2] data = 2               
[Thread_2] end writing data 
[Thread_1] data = 2 
[Thread_1] end reading data 
[Thread_2] start writing data 
[Thread_2] data = 3 
[Thread_2] end writing data 
[Thread_1] start reading data 
[Thread_2] start writing data 
[Thread_1] data = 3 
[Thread_1] end reading data 
[Thread_2] data = 4 
[Thread_2] end writing data 
Thread ID::3067669312 -----------E----------   //第二個線程結束
[Thread_1] start reading data 
[Thread_1] data = 4 
[Thread_1] end reading data 
Thread ID::3076062016 -----------E----------  //第一個線程結束

從上面的結果中大家可以看到,第二個線程還沒有寫完數據,第一個線程就開始讀取數據,而且讀取到的是共享數據的初始化值。可見他讀取到的值不是第二個線程修改後的數據,或者說不是准確的數據。再往下看,讀取數據的線程和修改數據的線程交替運行,因此線程運行順序也不正確。由此可見,如果不對線程進行同步操作,那麼對共享數據進行操作會生成錯誤的結果。

下面是使用互斥量同步線程後程序的運行結果,請大家參考:

Create first thread                //創建第一個線程
Create second thread               //創建第二個線程
Thread ID::3075980096 -----------S----------   
[Thread_1] start reading data    //第一個線程開始讀取數據(對數據的第一個操作是讀操作)
Thread ID::3067587392 -----------S---------- 
[Thread_1] data = 0              //第一個線程讀取到的是共享數據的初始值
[Thread_1] end reading data      //第一個線程讀取共享數據結束
[Thread_2] start writing data    //第二個線程開始修改共享數據的值
[Thread_2] data = 1              //第二個線程修改了共享數據的值
[Thread_2] end writing data      //第二個線程修改共享數據結束
[Thread_1] start reading data    //第一個線程開始讀取共享數據的值
[Thread_1] data = 1              //第一個線程讀取到了正確的共享數據的值
[Thread_1] end reading data      //第一個線程讀取共享數據結束
[Thread_2] start writing data 
[Thread_2] data = 2 
[Thread_2] end writing data 
[Thread_1] start reading data 
[Thread_1] data = 2 
[Thread_1] end reading data 
[Thread_2] start writing data 
[Thread_2] data = 3 
[Thread_2] end writing data 
[Thread_1] start reading data 
[Thread_1] data = 3 
[Thread_1] end reading data 
[Thread_2] start writing data 
[Thread_2] data = 4 
[Thread_2] end writing data 
Thread ID::3075980096 -----------E----------  //第一個線程結束
Thread ID::3067587392 -----------E----------  //第二個線程結束

從上面的結果中可以看到,第一個線程首先開始讀取數據,讀取完數據後第二個線程才開始修改數據;此時,第一個線程處於等待狀態,直到第二個線程修改完數據後才開始讀取數據,它讀取到了准確的共享數據。再往下看,讀取數據的線程和修改數據的線程依次有序地運行。由此可見,對線程進行同步操作後,對共享數據進行的操作順序是正確的,從共享數據中讀取到的值也是正確的。另外,再對比一下使用信號量對線程的同步操作。對共享數據的第一次操作是寫操作,而使用互斥量同步線程時,對共享數據的第一次操作是讀操作。正常來講,肯定是先對數據進行修改,然後才能讀數據中的內容。由此可見信號量對線程的運行順序更加嚴格一些。

依據我們的經驗來看,信號量經常用在計數或者對順序有嚴格要求的情況中,而互斥量經常用訪問共享資源的情況中。當然了,在同步線程的時候,大家可以依據自己的需要和程序的要求來選擇信號量和互斥量。

各位看官,關於線程同步之互斥量的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。


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