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之後,列