1. 程式人生 > >iOS訊號量機制

iOS訊號量機制

記得之前有講解過iOS多執行緒的處理,當時使用GCD的時候還有很多沒有講太清楚的地方,今天做一個小小的補充:
使用NSOperationQueue可以控制併發執行緒,但是如何在GCD中快速的控制併發呢?這裡就需要使用到訊號量(dispatch_semaphore)。訊號量是一個整型值並且具有一個初始計數值,並且支援兩個操作:訊號通知與等待。當一個訊號被訊號通知,其計數會被增加。當一個執行緒在一個訊號量上等待時,執行緒會被阻塞,直至計數器大於零,然後執行緒會減少這個計數。GCD中有三個函式與訊號量(dispatch_semaphore)相關,分別是
dispatch_semaphore_create   建立一個semaphore
 dispatch_semaphore_signal   傳送一個訊號
 dispatch_semaphore_wait    等待訊號
簡單的介紹一下這三個函式,第一個函式有一個整形的引數,我們可以理解為訊號的總量,dispatch_semaphore_signal是傳送一個訊號,自然會讓訊號總量加1,dispatch_semaphore_wait等待訊號,當訊號總量少於0的時候就會一直等待,否則就可以正常的執行,並讓訊號總量-1,根據這樣的原理,我們便可以快速的建立一個併發控制來同步任務和有限資源訪問控制。

    // 建立佇列組
    dispatch_group_t group = dispatch_group_create();   
// 建立訊號量,並且設定值為10
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);   
    for (int i = 0; i < 100; i++)   
    {   // 由於是非同步執行的,所以每次迴圈Block裡面的dispatch_semaphore_signal根本還沒有執行就會執行dispatch_semaphore_wait,從而semaphore-1.當迴圈10此後,semaphore等於0,則會阻塞執行緒,直到執行了Block的dispatch_semaphore_signal 才會繼續執行
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_group_async(group, queue, ^{ NSLog(@"%i",i); sleep(2); // 每次傳送訊號則semaphore會+1, dispatch_semaphore_signal(semaphore); }); } dispatch_group_wait(group
, DISPATCH_TIME_FOREVER); dispatch_release(group); dispatch_release(semaphore);

簡單的介紹一下這一段程式碼,建立了一個初使值為10的semaphore,每一次for迴圈都會建立一個新的執行緒,執行緒結束的時候會發送一個訊號,執行緒建立之前會訊號等待,所以當同時建立了10個執行緒之後,for迴圈就會阻塞,等待有執行緒結束之後會增加一個訊號才繼續執行,如此就形成了對併發的控制,如上就是一個併發數為10的一個執行緒佇列。