2012-10-29 44 views
1

您好,我正在做一個關於使用帶有多信號量的POSIX線程的任務。對任務的簡要說明是:有4個不同的數據包(char/video/audio/image),每個數據包由不同的線程攜帶,並且我們有一個共享緩衝區。用戶可以在系統上工作的最大線程數作爲輸入。例如;如果用戶輸入10,則可以創建最多10個線程,以在給定時間內通過緩衝區傳輸數據包。現在令我感到困惑的是,這個緩衝區可以立即包含有限的數據包。 (例如,它可以包含最多10個字符數據包和20個視頻數據包等),所以我們必須爲每種數據類型設置不同的信號量。我知道如何使用信號量來控制緩衝區大小,這很簡單,但不能設置使用信號量信息包的正確思想。即使我嘗試了一些不同的方法,我總是面臨死鎖錯誤。這裏是我的僞代碼,以更清楚地瞭解我的程序。關於使用多個信號量的同步

define struct packege 
define semaphore list 

main 

initialize variables and semaphores 

while threadCounter is less than MaxThreadNumber 

switch(random) 
case 0: create a character package 
    create a thread to insert the package in buffer 
case 1: create a video package 
    create a thread to insert the package in buffer 
case 2: create an image package 
    create a thread to insert the package in buffer 
case 3: create an audio package 
    create a thread to insert the package in buffer 

increment threadCounter by one 
end of while 

create only one thread which will make the dequeue operation 
end of main 

producer function 

for i->0 to size_of_package 
    sem_wait(empty_buffer) // decrement empty_buffer semaphore by size of package 

    lock_mutex 
     insert item into queueu 
     decrement counter of the buffer by size of package 
    unlock_mutex 

for i->0 to size_of_package 
    sem_post(full_buffer) // increment full_buffer semaphore by size of package 

end of producer function 

consumer function 

while TRUE // Loops forever 

    lock_mutex 

     if queue is not empty 
      dequeue 

     increment counter of the buffer size of package 

    unlock_mutex 

for i->0 to size_of_package // The reason why i making the sem_wait operation here is i cant make the dequeue in outer region of mutex. 
    sem_wait(full_buffer) 
for i->0 to size_of_package 
    sem_post(empty_buffer) 
end of consumer function 

與此實現程序正常工作。但我不能正確使用屬於包的線程的信號量。我可以聽取每個建議,並會爲每個答案而感激。

+0

在你的代碼中,消費者實際上並不知道它從緩衝區讀取什麼類型的數據。這個可以嗎? – didierc

+0

我認爲你的意思是表明你想用一個信號量來配置總線程併發線程數,而N信號量多一個用於每個數據包*類型*來定量任何單個數據包類型的併發線程數。這甚至接近準確嗎?有點困惑.. – WhozCraig

+0

@didierc yeap有沒有問題,我安排的參數,使其正常工作。首先,我將結構作爲參數發送給生產者,消費者在互斥體中進行出隊操作。隊列是全局定義的。 – quartaela

回答

1

這不是信號量的使用方式。緩衝區的控制變量/結構應該計算緩衝區中包含多少條消息以及哪些類型。互斥體保護緩衝區及其控制變量/結構免受不同線程的併發訪問。信號量(如果使用的話)只是向消費者發送緩衝區的狀態信號,並且沒有連接到數據包的大小;它肯定不會因數據包的大小而增加!

建議您最好使用pthread條件變量而不是信號量。它們與pthread互斥體一起使用,以保證線程之間無競爭信號。生產者循環執行此:

  • 鎖定互斥,
  • 修改緩衝等,以增加新的(多個)分組,
  • 信號的狀態變量,並
  • 解鎖互斥量。

消費者循環執行此:

  • 鎖定互斥,
  • 處理所有緩衝的數據,
  • 等待狀態變量。

閱讀上pthread_cond_initpthread_cond_signalpthread_cond_wait

+0

實際上,我知道如何使用條件變量,但是在他們想使用我們的信號量的任務中。像這樣'爲了舉例,緩衝區最多可以包含15個多媒體視頻數據包,這意味着第16個MM-視頻數據包必須被信號量利用所阻塞。' – quartaela

1

由於這是一項任務,因此您可能不需要具有真正的數據包讀寫數據,只需模擬其處理。

在這種情況下,問題歸結爲如何當他們達到他們可以在緩存寫入數據包的限制,有效地阻止了生產線。就目前而言,據我所知,您正在使用信號計數寫入緩衝區的數據包的各個元素。

想象一下,您在緩衝區中的寫入是原子的,而您只是想對數據包進行計數,而不是數據包元素。生產者每次寫入數據包時,都必須用適當的信號向消費者發信號,並且消費者每次讀取數據包時都必須發信號給適當的生產者。

讓我強調幾個其他點:

  • 信號燈的重要特性是當它達到零它會阻止。例如,如果它的初始值是10,在連續10次sem_get後,第11個將會被阻塞。
  • 您有4種類型的數據包,每種數據包的緩衝區中可寫入數量的閾值不同。

正如我所說的,製作人必須表示它寫了一個數據包,但它必須在達到閾值後停止。爲了達到這個目的,每當它發佈一個新數據包時,都要讓它獲取信號量,並使用sem_get。每次讀取數據包時,消費者都會執行sem_post,這與您使用單個信號量版本所做的相反。但是,由於您希望生產者在閾值處停止,因此您將初始化容量爲N - 1的信號量,N爲閾值。請注意,您必須在將新數據包寫入緩衝區後發出新的數據包信號,否則使用者可能會阻止緩衝區。

producer<type> function 

    write_packet() // put the packet in the buffer 
    sem_wait(type) // signal a new packet is available 
    // (if there's not enough space for another packet, the producer will block here) 

end producer<type> function 

consumer function 

    while TRUE // Loops forever 

     switch packet_available() // look if there's a new packet available 
     case video: 
     read_packet<video>() 
     sem_post(video) 
     (...) 
     default: // no packet available, just wait a little 
      sleep() 
     end if 
    end while 

你仍然需要定義packet_readpacket_writepacket_available功能,可能使用互斥來限制進入緩衝區。

+0

是的,你的理解是真實的。令人困惑的部分是。例如假設我創建了一個圖像數據。比'case 2:section'還是'producer function'_中的'sem_wait(&empty_image)'和'sem_post(&full_image)'應該更好?另一方面,這是一種正確的方式,我們有4個差異。消費者信號量操作中的類型將依賴於'if-else'語句。例如,'if(datatype == 1)sem_wait(&full_video)else if(datatype == 2)sem_wait(&empty_image)'etc – quartaela

+0

@quartaela:什麼是empty_image和full_image?爲什麼使用2個不同的信號量用於圖像數據包? – didierc

+0

empty_image初始化緩衝區可以容納的圖像數據的最大數量,並且full_image被初始化爲0,其計數緩衝區的全部部分。所以'舉例來說,緩衝區最多可以包含15個多媒體視頻數據包,這意味着第十六個MM-Video數據包必須被信號量利用所阻塞。「所以無論何時發送視頻數據包,我都會發信號給製作人添加最後一個。所以我爲每個數據類型定義了4個空的4個完整的信號量變量。是不是它的方式_? – quartaela