信號量是一個整形值並且具有一個初始計數值,並且支持兩個操作:信號通知和等待。當一個信號量被信號通知,其計數會被增加。當一個線程在一個信號量上等待時,線程會被阻塞(如果有必要的話),直至計數器大於零,然後線程會減少這個計數。
在GCD中有三個函數是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();
- 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++)
- {
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- dispatch_group_async(group, queue, ^{
- NSLog(@"%i",i);
- sleep(2);
- dispatch_semaphore_signal(semaphore);
- });
- }
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- dispatch_release(group);
- dispatch_release(semaphore);
簡單的介紹一下這一段代碼,創建了一個初使值爲10的semaphore,每一次for循環都會創建一個新的線程,線程結束的時候會發送一個信號,線程創建之前會信號等待,所以當同時創建了10個線程之後,for循環就會阻塞,等待有線程結束之後會增加一個信號才繼續執行,如此就形成了對併發的控制,如上就是一個併發數爲10的一個線程隊列。
簡單示例
- __block BOOL isok = NO;
- dispatch_semaphore_t sema = dispatch_semaphore_create(0);
- Engine *engine = [[Engine alloc] init];
- [engine queryCompletion:^(BOOL isOpen) {
- isok = isOpen;
- dispatch_semaphore_signal(sema);
- } onError:^(int errorCode, NSString *errorMessage) {
- isok = NO;
- dispatch_semaphore_signal(sema);
- }];
- dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
- dispatch_release(sema);