在作業系統這門課學到的訊號 (Semaphore),總算可以派上用場!還是實作比理論有感覺多了~iOS早已把它給實作出來,我們只要知道怎麼去用它就行了!
維基百科這麼解釋訊號 (Semaphore):
定義
信號標(Semaphore)又稱為號誌,它以一個整數變數,提供訊號,以確保在平行計算環境中,不同行程在存取共享資源時,不會發生衝突。是一種不需要使用忙碌等待(busy waiting)的一種方法。
在系統中,給予每一個行程一個信號標,代表每個行程目前的狀態,未得到控制權的行程會在特定地方被強迫停下來,等待可以繼續進行的訊號到來。如果信號量是一個任意的整數,通常被稱為計數訊號量(Counting semaphore),或一般訊號量(general semaphore);如果信號量只有二進位的0或1,稱為二進位訊號量(binary semaphore)。在linux系中,二進位訊號量(binary semaphore)又稱Mutex。
運作
計數訊號量具備兩種操作動作,之前稱為 V(又稱signal())與 P(wait())。 V操作會增加信號標 S的數值,P操作會減少它。
- 初始化,給與它一個非負數的整數值。
- 執行 P(wait()),信號標S的值將被減少。企圖進入臨界區段的行程,需要先執行 P(wait())。當信號標S減為負值時,行程會被擋住,不能繼續;當信號標S不為負值時,行程可以獲准進入臨界區段。
- 執行 V(又稱signal()),信號標S的值會被增加。結束離開臨界區段的行程,將會執行 V(又稱signal())。當信號標S不為負值時,先前被擋住的其他行程,將可獲准進入臨界區段。
我們實際來使用看看吧!
/**
Theme: Using Semaphore
IDE: Xcode 5
Language: Objective C
Date: 102/12/24
Author: HappyMan
Blog: https://cg2010studio.wordpress.com/
*/
-(void)testSemaphore
{
NSLog(@"Happy Start");
__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_queue_create("happy.queue", nil);
dispatch_async(queue, ^(void) {
int sum = 0;
for(int i = 0; i < 10000; i++)
sum += i;
NSLog(@"The sum is: %d", sum);
// signal the semaphore
NSLog(@"Before signal");
dispatch_semaphore_signal(sem);
NSLog(@"After signal");
});
// wait for the semaphore
NSLog(@"Before wait");
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"After wait");
}
執行結果:
Happy Start
Before wait
49995000
Before signal
After signal
After wait
最後兩行順序不一定,有可能After wait->After signal。
只要會用這三個方法,就夠嚕~直接看SDK裡的解釋。
- create
- wait
- signal
/*! * @function dispatch_semaphore_create * * @abstract * Creates new counting semaphore with an initial value. * * @discussion * Passing zero for the value is useful for when two threads need to reconcile * the completion of a particular event. Passing a value greather than zero is * useful for managing a finite pool of resources, where the pool size is equal * to the value. * * @param value * The starting value for the semaphore. Passing a value less than zero will * cause NULL to be returned. * * @result * The newly created semaphore, or NULL on failure. */ /*! * @function dispatch_semaphore_wait * * @abstract * Wait (decrement) for a semaphore. * * @discussion * Decrement the counting semaphore. If the resulting value is less than zero, * this function waits for a signal to occur before returning. * * @param dsema * The semaphore. The result of passing NULL in this parameter is undefined. * * @param timeout * When to timeout (see dispatch_time). As a convenience, there are the * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants. * * @result * Returns zero on success, or non-zero if the timeout occurred. */ /*! * @function dispatch_semaphore_signal * * @abstract * Signal (increment) a semaphore. * * @discussion * Increment the counting semaphore. If the previous value was less than zero, * this function wakes a waiting thread before returning. * * @param dsema The counting semaphore. * The result of passing NULL in this parameter is undefined. * * @result * This function returns non-zero if a thread is woken. Otherwise, zero is * returned. */
參考:WiKi – Semaphore、WiKi – 訊號標、多工筆記 (GCD)、Semaphore原理與操作說明、同步機制比較:Spinlock v.s. Mutex。

隨意留個言吧:)~