Just a Computer Graphics Studio & My Life

[iOS] 使用訊號 (Using Semaphore)

作業系統這門課學到的訊號 (Semaphore),總算可以派上用場!還是實作理論有感覺多了~iOS早已把它給實作出來,我們只要知道怎麼去用它就行了!

semaphore

維基百科這麼解釋訊號 (Semaphore)

定義

信號標(Semaphore)又稱為號誌,它以一個整數變數,提供訊號,以確保在平行計算環境中,不同行程在存取共享資源時,不會發生衝突。是一種不需要使用忙碌等待(busy waiting)的一種方法。

在系統中,給予每一個行程一個信號標,代表每個行程目前的狀態,未得到控制權的行程會在特定地方被強迫停下來,等待可以繼續進行的訊號到來。如果信號量是一個任意的整數,通常被稱為計數訊號量(Counting semaphore),或一般訊號量(general semaphore);如果信號量只有二進位的0或1,稱為二進位訊號量(binary semaphore)。在linux系中,二進位訊號量(binary semaphore)又稱Mutex。

運作

計數訊號量具備兩種操作動作,之前稱為 V(又稱signal())與 P(wait())。 V操作會增加信號標 S的數值,P操作會減少它。

  1. 初始化,給與它一個非負數的整數值。
  2. 執行 P(wait()),信號標S的值將被減少。企圖進入臨界區段的行程,需要先執行 P(wait())。當信號標S減為負值時,行程會被擋住,不能繼續;當信號標S不為負值時,行程可以獲准進入臨界區段。
  3. 執行 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

Advertisements

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: