程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
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.在創建線程的進程中使用sem_init函數把信號量A的值初始化為0; 3.在讀取數據的線程中使用sem_wait實現P操作; 4.在第寫數據的線程中修改數據,寫數據的操作完成後使用sem_post實現V操作; 5.在創建線程的進程中使用sem_destroy函數釋放信號量相關的資源;

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

在代碼中我們自己實現了讀/寫數據的函數,為了方便說明問題,在這兩個函數中都使用了延時操作,目的是為了說明讀或者寫數據需要一定的時間

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

讀操作還沒有完成,就開始寫操作,這樣會造成讀操作讀取的數據不准確; 寫操作還沒有完成,就開始讀操作,這樣會造成讀操作讀取的數據不准確;
void read_data(char * str) 
{
    printf("[%s] start reading data \n",str);
    sleep(1);        //延時操作
    printf("[%s] data = %d \n",str,data); //對數據進行讀操作,並且顯示數據
    printf("[%s] end reading data \n",str);
}
void write_data(char * str)
{
    printf("[%s] start writing data \n",str);
    sleep(1);        //延時操作
    data++;          //對數據進程寫操作
    printf("[%s] data = %d \n",str,data);
    printf("[%s] end writing data \n",str);
}

下面是程序的運行結果,請大家參考:

Create first thread          //創建第一個線程
Create second thread         //創建第二個線程
Thread ID::3076148032 -----------S---------- 
[Thread_1] start reading data      //第一個線程開始讀取數據(對數據的第一個操作是讀操作)
Thread ID::3067755328 -----------S---------- 
[Thread_2] start writing data      //第二個線程開始寫數據
[Thread_1] data = 0                //寫操作還沒有完成,第一個線程讀取到的數據是初始值
[Thread_1] end reading data 
[Thread_1] start reading data 
[Thread_2] data = 1         
[Thread_2] end writing data  //寫操作完成,第二個線程通過寫操作把數據修改為1
[Thread_1] data = 1          //寫操作完成,第一個線程讀取到的數據是寫操作修改後的數據
[Thread_1] end reading data 
[Thread_1] start reading data 
[Thread_2] start writing data 
[Thread_1] data = 1 
[Thread_1] end reading data 
Thread ID::3076148032 -----------E----------  //讀取數據的線程結束
[Thread_2] data = 2 
[Thread_2] end writing data 
[Thread_2] start writing data 
[Thread_2] data = 3 
[Thread_2] end writing data 
[Thread_2] start writing data 
[Thread_2] data = 4 
[Thread_2] end writing data 
Thread ID::3067755328 -----------E---------- //寫數據的結束結束

大家從上面的結果中可以看到,對數據的讀操作還沒有完成,寫操作就開始運行,或者是寫操作還沒有完成,讀操作就開始運行。總之,讀操作和寫操作混合運行,程序中讀操作顯示的數據不准確。

我們按照上面對信號量的操作步驟,在程序中添加了信號量,通過信號量來實現線程同步。在代碼中為了方便操作,只需要把宏定義代碼前的注釋去掉就可以:

//#define SEM_ENABLE 1

因為我們在代碼中使用宏來控制信號量,詳細如下:

#ifdef SEM_ENABLE
    res = sem_wait(&sem_value);
    if(res != 0)
    {
        printf(" sem wait failed \n");
    }
#endif
#ifdef SEM_ENABLE
        res = sem_post(&sem_value);
        if(res != 0)
        {
            printf(" sem post failed \n");
        }
#endif

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

Create first thread         //創建第一個線程
Create second thread        //創建第二個線程
Thread ID::3075992384 -----------S---------- 
Thread ID::3067599680 -----------S---------- 
[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::3075992384 -----------E----------  //讀取數據的線程結束
Thread ID::3067599680 -----------E----------  //寫數據的線程結束

從上面的運行結果中可以看到,在使用信號量對兩個線程進行同步操作後,讀取數據的線程和寫數據的線程依次運行:先寫數據,然後才讀數據。這樣保證了讀取到的數據是准確的。

另外,大家可以看到,主進程先創建讀取數據的線程,然後才創建寫數據的線程。因此,應該是先讀取數據,然後才寫數據。不過,因為我們使用信號量對線程進行了同步,程序運行時,先執行寫操作,然後才執行讀操作。因此,在運行結果中,對數據的第一個操作是寫操作。這一點可以和沒有使用信號量的程序運行結果進行對比。

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


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