1. 程式人生 > >ios GCD之訊號量機制

ios GCD之訊號量機制

一,什麼是訊號量機制

   抽象說:

    訊號量是一個整型值並且具有一個初始計數值,並且支援兩個操作:訊號通知和等待。當一個訊號量被訊號通知,其計數會被增加。當一個執行緒在一個訊號量上等待時,假如此時的訊號量的整型值為0, 執行緒會被阻塞(因為等待會讓訊號量的整型值減一) , 假如我們此時給這個訊號量一個訊號通知,使計數器大於零,然後執行緒會繼續執行且會減少這個計數(執行等待訊號,讓這個計數減一)。

  簡單說:

     假如將訊號量,比作一個整型的變數a, 給它一個初始化值2當a(訊號量) 被訊號通知時,a的值就變成了1; 當執行緒在a上等待了(等待有相應的方法可操作),會線上程等待之後檢查a是否小於0, 假如不小於0,執行緒就會繼續執行; 假如a為0,在訊號量上等待的執行緒就會在此暫時停止,系統會等待其它執行緒讓此訊號量(也就是a)被訊號通知(有相應的方法可操作),讓其值大於0或等於0,這樣等待的執行緒就會繼續執行

。當然,如果就一個執行緒,並且執行緒等待了,沒有其它的執行緒讓其訊號量被訊號通知,程式就會崩潰

  舉例:
      關於訊號量,一般可以用停車來比喻
     
停車場剩餘4個車位,那麼即使同時來了四輛車也能停的下。如果此時來了五輛車,那麼就有一輛需要等待。

  訊號量的值就相當於剩餘車位的數目,dispatch_semaphore_wait函式就相當於來了一輛車,dispatch_semaphore_signal

  就相當於走了一輛車。停車位的剩餘數目在初始化的時候就已經指明瞭(dispatch_semaphore_create(long value)),

  呼叫一次dispatch_semaphore_signal,剩餘的車位就增加一個;呼叫一次dispatch_semaphore_wait剩餘車位就減少一個;

  當剩餘車位為0時,再來車(即呼叫dispatch_semaphore_wait)就只能等待。有可能同時有幾輛車等待一個停車位。有些車主

  沒有耐心,給自己設定了一段等待時間,這段時間內等不到停車位就走了,如果等到了就開進去停車。而有些車主就像把車停在這,

  所以就一直等下去。

二,訊號量設計的具體函式

     dispatch_semaphore是GCD用來同步的一種方式,與他相關的共有三個函式,分別是

    1. 建立訊號量,可以設定訊號量的資源數。0表示沒有資源,呼叫dispatch_semaphore_wait會立即等待。

          dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    2. 等待訊號,可以設定超時引數。該函式返回0表示得到通知,非0表示超時。

          dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    3. 通知訊號,如果等待執行緒被喚醒則返回非0,否則返回0。

         dispatch_semaphore_signal(semaphore);

下面我們逐一介紹三個函式:

(1)dispatch_semaphore_create的宣告為:

    dispatch_semaphore_t  dispatch_semaphore_create(long value);

    傳入的引數為long,輸出一個dispatch_semaphore_t型別且值為value的訊號量。

    值得注意的是,這裡的傳入的引數value必須大於或等於0,否則dispatch_semaphore_create會返回NULL。

   (關於訊號量,我就不在這裡累述了,網上很多介紹這個的。我們這裡主要講一下dispatch_semaphore這三個函式的用法)。

(2)dispatch_semaphore_signal的宣告為:

    long dispatch_semaphore_signal(dispatch_semaphore_t dsema)

   這個函式會使傳入的訊號量dsema的值加1;

 (3) dispatch_semaphore_wait的宣告為:

   long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);

   這個函式會使傳入的訊號量dsema的值減1;

   這個函式的作用是這樣的,如果dsema訊號量的值大於0,該函式所處執行緒就繼續執行下面的語句,並且將訊號量的值減1;

   如果desema的值為0,那麼這個函式就阻塞當前執行緒等待timeout(注意timeout的型別為dispatch_time_t,

   不能直接傳入整形或float型數),如果等待的期間desema的值被dispatch_semaphore_signal函式加1了,

   且該函式(即dispatch_semaphore_wait)所處執行緒獲得了訊號量,那麼就繼續向下執行並將訊號量減1。

   如果等待期間沒有獲取到訊號量或者訊號量的值一直為0,那麼等到timeout時,其所處執行緒自動執行其後語句。

(4)dispatch_semaphore_signal的返回值為long型別,當返回值為0時表示當前並沒有執行緒等待其處理的訊號量,其處理

   的訊號量的值加1即可。當返回值不為0時,表示其當前有(一個或多個)執行緒等待其處理的訊號量,並且該函式喚醒了一

   個等待的執行緒(當執行緒有優先順序時,喚醒優先順序最高的執行緒;否則隨機喚醒)。

   dispatch_semaphore_wait的返回值也為long型。當其返回0時表示在timeout之前,該函式所處的執行緒被成功喚醒。

   當其返回不為0時,表示timeout發生。

(5)在設定timeout時,比較有用的兩個巨集:DISPATCH_TIME_NOW 和 DISPATCH_TIME_FOREVER。

   DISPATCH_TIME_NOW  表示當前;

   DISPATCH_TIME_FOREVER  表示遙遠的未來;

   一般可以直接設定timeout為這兩個巨集其中的一個,或者自己建立一個dispatch_time_t型別的變數。

  建立dispatch_time_t型別的變數有兩種方法,dispatch_time和dispatch_walltime。

  利用建立dispatch_time建立dispatch_time_t型別變數的時候一般也會用到這兩個變數。

  dispatch_time的宣告如下:

  dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta);

  其引數when需傳入一個dispatch_time_t型別的變數,和一個delta值。表示when加delta時間就是timeout的時間。

  例如:dispatch_time_t  t = dispatch_time(DISPATCH_TIME_NOW, 1*1000*1000*1000);

     表示當前時間向後延時一秒為timeout的時間。

(6)程式碼舉簡單示例如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25    dispatch_semaphore_t sign = dispatch_semaphore_create(1); __block long x = 0; NSLog(@"0_x:%ld",x); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ sleep(1); NSLog(@"waiting"); x = dispatch_semaphore_signal(signal); NSLog(@"1_x:%ld",x); sleep(2); NSLog(@"waking"); x = dispatch_semaphore_signal(signal); NSLog(@"2_x:%ld",x); }); x = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER); NSLog(@"3_x:%ld",x); x = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER); NSLog(@"wait 2"); NSLog(@"4_x:%ld",x); x = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER); NSLog(@"wait 3"); NSLog(@"5_x:%ld",x);

最終列印的結果為:

1 2 3 4 5 6 7 8 9 10 2014-08-11 22:51:54.734 LHTest[15700:70b] 0_x:0 2014-08-11 22:51:54.737 LHTest[15700:70b] 3_x:0 2014-08-11 22:51:55.738 LHTest[15700:f03] waiting 2014-08-11 22:51:55.739 LHTest[15700:70b] wait 2 2014-08-11 22:51:55.739 LHTest[15700:f03] 1_x:1 2014-08-11 22:51:55.739 LHTest[15700:70b] 4_x:0 2014-08-11 22:51:57.741 LHTest[15700:f03] waking 2014-08-11 22:51:57.742 LHTest[15700:f03] 2_x:1 2014-08-11 22:51:57.742 LHTest[15700:70b] wait 3 2014-08-11 22:51:57.742 LHTest[15700:70b] 5_x:0

相關推薦

ios GCD訊號機制

一,什麼是訊號量機制    抽象說:     訊號量是一個整型值並且具有一個初始計數值,並且支援兩個操作:訊號通知和等待。當一個訊號量被訊號通知,其計數會被增加。當一個執行緒在一個訊號量上等待時,假如此時的訊號量的整型值為0, 執行緒會被阻塞(因為等待會讓訊號量的整型

GCD訊號機制

在使用NSOperationQueue進行多執行緒程式設計時,可通過[queue setMaxConcurrentOperationCount:5]來設定執行緒池中最多並行的執行緒數,在GCD中訊號量機制也和它相似,可以控制併發的執行緒數量。 1.首先熟悉下幾個函式

iOS系統GCD學習(5):訊號機制

當我們在處理一系列執行緒的時候,當數量達到一定量,在以前我們可能會選擇使用NSOperationQueue來處理併發控制,但如何在GCD中快速的控制併發呢?答案就是dispatch_semaphore,對經常做unix開發的人來講,我所介紹的內容可能就顯得非常入門級了,訊

Linux核心同步機制訊號和互斥體

訊號量:訊號量(semaphore)是程序間通訊處理同步互斥的機制。是在多執行緒環境下使用的一種措施,它負責協調各個程序,以保證他們能夠正確、合理的使用公共資源。 它和spin lock最大的不同之處就是:無法獲取訊號量的程序可以睡眠,因此會導致系統排程。原理訊號量一般可以用

iOS訊號機制

記得之前有講解過iOS多執行緒的處理,當時使用GCD的時候還有很多沒有講太清楚的地方,今天做一個小小的補充: 使用NSOperationQueue可以控制併發執行緒,但是如何在GCD中快速的控制併發呢?這裡就需要使用到訊號量(dispatch_semaphor

linux下多執行緒同步機制訊號、互斥、讀寫鎖、條件變數

之前有寫過類似的部落格,這東西不用老忘,現在又有更清晰的理解了。 一、訊號量 編譯時候加入-lrt 訊號量最基本的兩個操作就是PV操作:P()操作實現訊號量減少,V()操作實現訊號量的增加 訊號量的值取決於訊號量的型別,訊號量的型別有多種: (1)二進位制訊號量:0與1.

linux同步機制訊號down 和up

訊號量(semaphore)   Linux核心的訊號量在概念和原理上和使用者態的System V的IPC機制訊號量是相同的,不過他絕不可能在核心之外使用,因此他和System V的IPC機制訊號量毫不相干。   訊號量在建立時需要設定一個初始值,表示同時能有幾個任務能訪問

IOS多執行緒使用GCD訊號實現生產者與消費者模式

一、原理的簡述   在生產者消費者模式當中,首先需要分清在這個模式當中有哪些角色? 各角色分別擔任什麼職責與它們之間的關係如何? 角色之間是在保證資料的準確性的情況下如何通訊(同步資料)的? 假設現在有一個這樣的情形: 有兩個人共同訪問一個容量有限的倉庫,這2個人,

linux 多執行緒訊號 sem_init

1. 什麼是訊號量 linux sem 訊號量是一種特殊的變數,訪問具有原子性, 用於解決程序或執行緒間共享資源引發的同步問題。 使用者態程序對 sem 訊號量可以有以下兩種操作: 等待訊號量 當訊號量值為 0 時,程式等待;當訊號量值大於 0 時,訊號量減 1,程式

【OS】訊號機制

儲存一下自己看,侵刪。 原文地址:http://blog.csdn.net/speedme/article/details/17597373 上篇部落格中(程序同步之臨界區域問題及Peterson演算法),我們對臨界區,臨界資源,鎖機制詳細解讀了下,留下了一個問題,就是鎖機制只能判斷臨界資源是否被佔用,所

訊號機制中的down和up函式

轉自:https://blog.csdn.net/fzubbsc/article/details/37737159 參考: https://blog.csdn.net/liuxd3000/article/details/17913363 http://blog.chinaunix.net

第二章 2.3 訊號機制

整形訊號量: 訊號量定義為一個整型量; 根據初始情況賦相應的值; 僅能通過兩個原子操作來訪問 P 操作: wait(S): While S<=0 do no-op; S:=S-1;

Linux訊號

訊號量概念 Dijkstra提出的“訊號量”概念是共發程式設計領域的一項重大進步 訊號量是一種變數,它只能取正整數值,對這些正整數只能進行兩種操作:等待和訊號 用兩種記號來表示訊號量的這兩種操作:     P(semaphore variable) 代表等待     V(s

4.IPC訊號 //依據RT-Thread核心程式設計的學習記錄(非核心實現)

IPC: Inter proess communication   大的任務中的各任務資訊互動配合,內容包括訊號量,互斥鎖,訊號,訊息佇列,郵箱     本篇文章,只討論第一個內容,訊號量 1.訊號量的建立 和執行緒的建立方式類似,訊號量的建立也分動態dynamic和靜態

計算機作業系統感悟隨筆--訊號機制

2.訊號量的基本應用 實現程序互斥 實現程序間的前趨關係(有序) 3.整型訊號量 把整型訊號量定義為一個表示資源數目的整型量S,除初始化外,僅能通過兩個標準的原子操作wait(S)和signal(S)來訪問。 wait(S)和signal(S)操作可以描述為

Python並行程式設計(五):執行緒同步訊號

1、基本概念       訊號量是由作業系統管理的一種抽象資料型別,用於在多執行緒中同步對共享資源的使用。本質上說,訊號量是一個內部資料,用於標明當前的共享資源可以有多少併發讀取。       同樣在threading中,訊號量有acquire和release兩個函式。       - 每當執行緒想要讀取關聯

linux程序控制訊號 semget,semctl,semop

轉載自 https://www.cnblogs.com/52php/p/5851570.html 這篇文章將講述別一種程序間通訊的機制——訊號量。注意請不要把它與之前所說的訊號混淆起來,訊號與訊號量是不同的兩種事物。有關訊號的更多內容,可以閱讀我的另一篇文章:L

Alios things學習訊號與互斥

Sem訊號量  1. 概念 任務可以通過獲取訊號量來獲取訪問共享資源的“門禁”,可以通過配置訊號量數目,讓多個任務同時獲取門禁,當無法獲取時,任務會按照優先順序排隊獲取“門禁”,缺點是存在優先順序翻轉問題。  2. sem操作      1)靜態建立:kstat

Java執行緒訊號

 計數訊號量用來控制同時訪問某個特定資源的運算元量,或者同時執行某個指定操作的數量。計數訊號量還可以用來實現某種資源池,或者對容器施加邊界。  Semaphore中管理者一組虛擬的許可,許可的數量可通過建構函式來指定。在互相操作時可以首先獲得許可(只要還有剩餘的許可),並在使用以後釋放許可。

iOS -- GCD延遲與定時器

我們開發常用的定時器有三種:NSTimer,CADisplyLink,CGD 本文詳細說一下CGD的延遲與定時器方法。文章最後,也會說說GCD與前兩個的區別。 直接上程式碼,首先是延遲的程式碼: 其中的delayInSeconds就是延遲的時間,執行之後,輸出臺會在2s之後,列