2011-07-06 57 views
3

documentation for dispatch_semaphore_wait表示它「以FIFO的順序等待信號」。但在這個例子中似乎沒有 - 請問有人能解釋一下嗎?是不是dispatch_semaphore_wait FIFO?

實施例:

#include <dispatch/dispatch.h> 
#include <stdio.h> 

dispatch_queue_t q1, q2; 
dispatch_semaphore_t sem; 
int g_call; 

void do_work(void) 
{ 
    int s = 0; 
    int i; 
    for (i = 0; i < 100000000; ++i) 
     ++s; 
} 

void f1(int call) 
{ 
__block int waited = 0; 
    dispatch_async(q1, ^{ 
     while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000))) 
      waited = 1; 
     printf("1:%d %s\n", call, waited ? "waited" : ""); 
     do_work(); 
     dispatch_semaphore_signal(sem); 
    }); 
} 

void f2(int call) 
{ 
    __block int waited = 0; 
    dispatch_async(q2, ^{ 
     while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000))) 
      waited = 1; 
     printf("\t\t2:%d %s\n", call, waited ? "waited" : ""); 
     do_work(); 
     dispatch_semaphore_signal(sem); 
    }); 
} 

int main(int argc, char **argv) 
{ 
    q1 = dispatch_queue_create(NULL, NULL); 
    q2 = dispatch_queue_create(NULL, NULL); 
    sem = dispatch_semaphore_create(1); 
    g_call = 0; 

    dispatch_queue_t q_global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q_global); 
    const uint64_t DELAY = 10; 
    dispatch_source_set_event_handler(timer, ^{ 
     f1(g_call); 
     f2(g_call); 
     ++g_call; 
     dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0); 
    }); 
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0); 
    dispatch_resume(timer); 

    sleep(3); 
} 

預期輸出:

1:0 
     2:0 
1:1 
     2:1 
1:2 
     2:2 
... 

實際輸出(一個例子):

1:0 
1:1 
... 
1:14 
     2:0 waited 
     2:1 
     ... 

編輯:如果實際輸出,而不是被串行隊列,q1和q2被設置爲全局隊列:

1:0 
     2:8 waited 
1:3 waited 
1:4 waited 
     2:3 waited 
1:6 waited 
1:9 waited 
     2:9 waited 
     2:21 
1:28 waited 

(有時它完美,但有時它的怪異這樣的。)

回答

3

dispatch_queue_create創建一個串行隊列,然後串行隊列創建並行線程的線程(我不那麼肯定...... )。

dispatch_semaphore_wait使用自旋鎖來獲取性能的信號量。這意味着它不是作爲pthread_mutex_lock的上下文切換點。它不經常切換上下文。

如果您使用全局隊列,您的代碼將按照您的預期輸出(但它不完全相同)。因爲全局隊列使用pthread工作隊列。切換上下文的行爲不同於pthread線程的行爲。

q1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
q2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

EDITED:

全局隊列順序執行給定的任務,但這些任務正在執行同時地,輸出順序可以通過上下文切換而變化。而且,你的代碼的計時器每10納秒觸發一次,太多的任務正在併發執行。

另一個簡單的例子,

dispatch_queue_t queue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_apply(10, queue, ^(size_t index) { 
    printf("%zu\n", index); 
}); 

在我8core的MacBook Pro:

4 
2 
0 
6 
3 
1 
5 
8 
9 
7 
+0

感謝您的幫助explanation--。但是如果我讓q1和q2成爲全局隊列,有時候它會起作用,但有時輸出卻完全失序。查看我的編輯。任何想法爲什麼發生這種情況? (我不確定這是信號量還是全局隊列正在進行重新排序。) – jlstrecker

+0

更新了我的答案。 –