dispatch_semaphore信号量是GCD用來同步的一種方式。
信号量通常用在 允許幾個線程同時通路一個資源,通過信号量來控制通路的線程個數.
與他相關的共有三個函數,分别是
dispatch_semaphore_create,dispatch_semaphore_signal,dispatch_semaphore_wait。
(1)dispatch_semaphore_create的聲明為:
dispatch_semaphore_t dispatch_semaphore_create(long value);
其中value為信号量的初值,如果小于0則會傳回NULL ,傳回dispatch_semaphore_t類型的信号量。
(2)dispatch_semaphore_signal的聲明為:
long dispatch_semaphore_signal(dispatch_semaphore_t dsema)
提高信号量,使傳入的信号量的值加1;
傳回值為long類型,
當傳回值為0時,表示目前 已經沒有線程等待其處理 (的信号量)
當傳回值不為0時,表示其目前 有(一個或多個)線程等待其處理(的信号量),并喚醒一 個等待的線程
注:(當線程有優先級時,喚醒優先級最高的線程;否則随機喚醒,線程一級一級的喚醒,直到傳回0)
(3) dispatch_semaphore_wait的聲明為:
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
等待降低信号量,使傳入的信号量的值減1;
傳回值為long類型,
當傳回值為0時 表示在timeout(時間長度)之前,該函數所處的線程被成功喚醒。
當其傳回不為0時,表示阻塞線程 timeout時間。
函數的作用: 如果信号量的值大于0,該線程就繼續執行下面的語句
如果信号量的值為0,那麼阻塞目前線程 等待timeout(時間長度)
(注意timeout的類型為dispatch_time_t,不能直接傳入整形或float型數)。
注:在設定timeout時,比較有用的兩個宏:DISPATCH_TIME_NOW 和 DISPATCH_TIME_FOREVER。
DISPATCH_TIME_NOW 表示目前;
DISPATCH_TIME_FOREVER 表示遙遠的未來;
舉例分析
<pre name="code" class="objc">//
// ViewController.swift
// SwiftTestExample
//
// Created by huangwenchen on 15/1/6.
// Copyright (c) 2015年 huangwenchen. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
var semaphore:dispatch_semaphore_t;
required init(coder aDecoder: NSCoder) {
self.semaphore = dispatch_semaphore_create(1)
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), {() -> Void in
self.task_first()
})
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), { () -> Void in
self.task_second()
})
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), { () -> Void in
self.task_third()
})
// Do any additional setup after loading the view, typically from a nib.
}
func task_first(){
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER)
NSLog("%@","First task starting")
sleep(1)
NSLog("%@", "First task is done")
dispatch_semaphore_signal(self.semaphore)
}
func task_second(){
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER)
NSLog("%@","Second task starting")
sleep(1)
NSLog("%@", "Second task is done")
dispatch_semaphore_signal(self.semaphore)
}
func task_third(){
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER)
NSLog("%@","Thrid task starting")
sleep(1)
NSLog("%@", "Thrid task is done")
dispatch_semaphore_signal(self.semaphore)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
這段代碼模拟送出三個任務,送出到全局隊列(并行隊列)
當信号量的初初始為2時候
輸出
2015-01-06 19:42:01.963 SwiftTestExample[632:11631] First task starting
2015-01-06 19:42:01.964 SwiftTestExample[632:11630] Second task starting
2015-01-06 19:42:02.971 SwiftTestExample[632:11630] Second task is done
2015-01-06 19:42:02.971 SwiftTestExample[632:11631] First task is done
2015-01-06 19:42:02.971 SwiftTestExample[632:11633] Thrid task starting
2015-01-06 19:42:03.974 SwiftTestExample[632:11633] Thrid task is done
當信号量為3的時候
2015-01-06 19:42:49.912 SwiftTestExample[666:12259] First task starting
2015-01-06 19:42:49.912 SwiftTestExample[666:12258] Second task starting
2015-01-06 19:42:49.912 SwiftTestExample[666:12260] Thrid task starting
2015-01-06 19:42:50.915 SwiftTestExample[666:12259] First task is done
2015-01-06 19:42:50.915 SwiftTestExample[666:12260] Thrid task is done
2015-01-06 19:42:50.915 SwiftTestExample[666:12258] Second task is done
當信号量為1的時候
2015-01-06 19:43:35.140 SwiftTestExample[694:12768] First task starting
2015-01-06 19:43:36.145 SwiftTestExample[694:12768] First task is done
2015-01-06 19:43:36.145 SwiftTestExample[694:12771] Second task starting
2015-01-06 19:43:37.146 SwiftTestExample[694:12771] Second task is done
2015-01-06 19:43:37.146 SwiftTestExample[694:12769] Thrid task starting
2015-01-06 19:43:38.150 SwiftTestExample[694:12769] Thrid task is done