結(jié)合GCD簡(jiǎn)單介紹下同步喊崖、異步、并行雇逞、串行荤懂、線程、多線程等概念

一塘砸、簡(jiǎn)單問答環(huán)節(jié)

1.什么是GCD

答:一種異步執(zhí)行任務(wù)的技術(shù)

2.什么是線程

答:源代碼通過(guò)編譯器轉(zhuǎn)換為CPU命令列节仿,即二進(jìn)制代碼,一個(gè)CPU執(zhí)行這些二進(jìn)制代碼的形式為一行一行執(zhí)行掉蔬,執(zhí)行順序是線性的(永遠(yuǎn)不會(huì)出現(xiàn)分叉)廊宪,即為線程

3.什么是多線程

答:一個(gè)CPU執(zhí)行多條這種線性的無(wú)分叉路徑,即為多線程

4.一個(gè)CPU如何實(shí)現(xiàn)多線程

答:一個(gè)CPU同時(shí)只能做一件事女轿,當(dāng)CPU在多個(gè)線程間頻繁的切換箭启,由于速度很快,給人的感覺就是同時(shí)執(zhí)行多個(gè)線程

5.多線程會(huì)產(chǎn)生哪些問題

答:1.更新相同的資源谈喳,導(dǎo)致數(shù)據(jù)不一致(數(shù)據(jù)競(jìng)爭(zhēng))
2.多個(gè)線程之間相互等待,誰(shuí)也不往下執(zhí)行(死鎖)
3.多線程對(duì)內(nèi)存消耗很大
還有很多問題戈泼,不一一列舉

二婿禽、結(jié)合GCD的API講解

1.Dispatch Queue(調(diào)度隊(duì)列)

a.隊(duì)列的種類

隊(duì)列可以通俗的理解為坐火車檢票赏僧,乘客排著隊(duì)準(zhǔn)備通過(guò)檢票口,而每一個(gè)乘客相當(dāng)于一個(gè)要執(zhí)行的代碼塊(任務(wù))
隊(duì)列總體分為兩種類型 Serial Dispatch QueueConcurrent Dispatch Queue扭倾,可以通俗的理解為一個(gè)檢票口淀零,和多個(gè)檢票口(即串行隊(duì)列和并行隊(duì)列)
Serial Dispatch Queue 類型的隊(duì)列每次只允許一個(gè)乘客通過(guò),后面的乘客想通過(guò)檢票口膛壹,必須要等前面的乘客先通過(guò)(每次只能執(zhí)行一個(gè)代碼塊)
Concurrent Dispatch Queue 類型的隊(duì)列相當(dāng)于有多個(gè)檢票口驾中,可以同時(shí)允許很多乘客檢票(即同時(shí)執(zhí)行很多個(gè)代碼塊)

b.創(chuàng)建一個(gè)隊(duì)列

隊(duì)列的類型是dispatch_queue_t創(chuàng)建一個(gè)隊(duì)列用dispatch_queue_create方法

// 創(chuàng)建一個(gè)Serial類型的隊(duì)列
dispatch_queue_t   serial_queue = dispatch_queue_create("com.ms.serial", NULL);

// 創(chuàng)建一個(gè)concurrent類型的隊(duì)列
    dispatch_queue_t     concurrent_queue = dispatch_queue_create("com.ms.concurrent", DISPATCH_QUEUE_CONCURRENT);

第一個(gè)參數(shù)是隊(duì)列的名字,一般用程序ID逆序全域名的形式模聋,這個(gè)參數(shù)在程序報(bào)錯(cuò)時(shí)候的返回信息中會(huì)體現(xiàn)肩民,還是很有用的
第二個(gè)參數(shù)為生成指定類型隊(duì)列的參數(shù)

注意

  • 每生成一個(gè)Serial類型的隊(duì)列相當(dāng)于生成并使用一個(gè)線程,所以不宜生成過(guò)多的Serial類型隊(duì)列链方,這樣內(nèi)存會(huì)開銷很大
  • 一個(gè)線程對(duì)數(shù)據(jù)來(lái)說(shuō)是安全的持痰,所以可以針對(duì)一個(gè)數(shù)據(jù)生成一個(gè)Serial類型的隊(duì)列,例如更新一個(gè)文件祟蚀,但是要避免針對(duì)一個(gè)文件生成多個(gè)Serial類型的隊(duì)列工窍,因?yàn)槎嗑€程的關(guān)系,會(huì)產(chǎn)生數(shù)據(jù)競(jìng)爭(zhēng)
  • 當(dāng)想要對(duì)一個(gè)數(shù)據(jù)進(jìn)行并發(fā)操作前酿,又要避免數(shù)據(jù)競(jìng)爭(zhēng)問題的時(shí)候患雏,用Concurrent類型的隊(duì)列,系統(tǒng)會(huì)有效的管理這些線程罢维,避免出現(xiàn)問題

c.系統(tǒng)自帶的隊(duì)列

GCD的API為我們準(zhǔn)備了兩個(gè)隊(duì)列Main Dispatch QueueGlobal Dispatch Queue分別對(duì)應(yīng)Serial類型的隊(duì)列和Concurrent類型的隊(duì)列

// 獲取Main Dispatch Queue
dispatch_queue_t main_queue = dispatch_get_main_queue();
// 獲取Global Dispatch Queue
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

Global Dispatch Queue有四種執(zhí)行優(yōu)先級(jí)淹仑,高優(yōu)先級(jí)相當(dāng)于會(huì)員的作用,可以讓你插隊(duì)言津,對(duì)應(yīng)dispatch_get_global_queue方法的第一個(gè)參數(shù)攻人,分別是

參數(shù) 優(yōu)先級(jí)
DISPATCH_QUEUE_PRIORITY_HIGH 高優(yōu)先級(jí)
DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn)優(yōu)先級(jí)
DISPATCH_QUEUE_PRIORITY_LOW 低優(yōu)先級(jí)
DISPATCH_QUEUE_PRIORITY_BACKGROUND 后臺(tái)優(yōu)先級(jí)

需要注意,優(yōu)先級(jí)只是大致的判斷悬槽,并不是絕對(duì)的

d.修改隊(duì)列優(yōu)先級(jí)

dispatch_queue_create方法創(chuàng)建的隊(duì)列優(yōu)先級(jí)與Global Dispatch Queue的默認(rèn)優(yōu)先級(jí)相同怀吻,即DISPATCH_QUEUE_PRIORITY_DEFAULT
想變更生成的隊(duì)列的優(yōu)先級(jí)的時(shí)候,用方法dispatch_set_target_queue
例子是將創(chuàng)建的concurrent_queue的優(yōu)先級(jí)設(shè)置成DISPATCH_QUEUE_PRIORITY_BACKGROUND優(yōu)先級(jí)

// 創(chuàng)建的隊(duì)列初婆,優(yōu)先級(jí)是DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_queue_t concurrent_queue = dispatch_queue_create("com.ms.concurrent", DISPATCH_QUEUE_CONCURRENT);
// 獲取的Global Dispatch Queue對(duì)列蓬坡,注意優(yōu)先級(jí)是 DISPATCH_QUEUE_PRIORITY_BACKGROUND
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
// 修改concurrent_queue的優(yōu)先級(jí)
dispatch_set_target_queue(concurrent_queue, global_queue);

注意

  • 不可以修改Main Dispatch Queue 和 Global Dispatch Queue的優(yōu)先級(jí)

dispatch_set_target_queue的另一個(gè)作用是可以決定隊(duì)列的執(zhí)行層次,防止多個(gè)隊(duì)列并行執(zhí)行
假設(shè)有五個(gè)Serial Dispatch Queue磅叛,那么這五個(gè)Serial Dispatch Queue是并行執(zhí)行的屑咳,如果將其中四個(gè)Serial Dispatch Queue設(shè)置為其中某一個(gè)Serial Dispatch Queue的優(yōu)先級(jí),則不會(huì)出現(xiàn)并行執(zhí)行的情況

2.添加任務(wù)到隊(duì)列

前面已經(jīng)講解了如何創(chuàng)建一個(gè)隊(duì)列弊琴,下面介紹如何將任務(wù)添加到隊(duì)列中
將任務(wù)添加到隊(duì)列分為同步(sync)異步(async)
舉個(gè)例子兆龙,你有車了,為了嘚瑟有車敲董,要開車去送你的朋友去火車站坐火車紫皇,但是你可能有好幾個(gè)朋友要去坐火車慰安,但是這幾個(gè)朋友之間相互不認(rèn)識(shí),分別在不同的地方聪铺,要分別送他們
同步(sync)就是你送一個(gè)朋友去火車站之后化焕,必須確認(rèn)你朋友經(jīng)過(guò)檢票口上了火車之后你才回去接其他的朋友,也不管其他的朋友是否著急
異步(async)就是你送去一個(gè)朋友之后铃剔,也沒管它是否檢票上車撒桨,就返回去接其他的朋友了

a. dispatch_sync()

void  dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

將任務(wù)同步添加到隊(duì)列中
例子是將打印1的任務(wù)同步添加到serial_queue隊(duì)列中

dispatch_queue_t serial_queue = dispatch_queue_create("com.ms.serial", NULL);
dispatch_sync(serial_queue, ^{
        // 要做的任務(wù)
        NSLog(@"1");
    });
  • 第一個(gè)參數(shù)是要添加的隊(duì)列
  • 第二個(gè)參數(shù)是block,就是我們要添加的任務(wù)

b. dispatch_sync_f()

void  dispatch_sync_f(dispatch_queue_t queue, void *_Nullable context, dispatch_function_t work);

作用和dispatch_sync()方法一樣键兜,不同點(diǎn)是這個(gè)方法可以將函數(shù)提交到隊(duì)列中
例子中是將一個(gè)函數(shù)print1()添加到隊(duì)列中凤类,實(shí)現(xiàn)的也是打印1的任務(wù)

void print1(void *param){
    printf("%s", param);
}
char *str = "1";
dispatch_sync_f(serial_queue, str, print1);
  • 第一個(gè)參數(shù)是要添加的隊(duì)列
  • 第二個(gè)參數(shù)是地址,這個(gè)參數(shù)是第三個(gè)參數(shù)(一個(gè)函數(shù))要用的參數(shù)
  • 第三個(gè)參數(shù)是一個(gè)void (*dispatch_function_t)(void *_Nullable)類型的函數(shù)

c. dispatch_async()和dispatch_async_f()

類比上面的ab蝶押,就是同步和異步的區(qū)別

將任務(wù)添加到隊(duì)列后踱蠢,系統(tǒng)會(huì)對(duì)隊(duì)列進(jìn)行retain,當(dāng)任務(wù)完成后隊(duì)列被release

注意

  • dispatch_sync()和dispatch_async()中第二個(gè)參數(shù)是block棋电,這個(gè)block中即使使用self也不會(huì)出現(xiàn)循環(huán)引用的情況茎截,可以放心使用
  • dispatch_sync()別亂用,在串行隊(duì)列中用dispatch_sync()將任務(wù)添加到當(dāng)前串行隊(duì)列赶盔,會(huì)發(fā)生死鎖企锌,因?yàn)閎lock的執(zhí)行需要等待前面的任務(wù),也就是dispatch_sync執(zhí)行完成于未,兩者互相等待撕攒,在并行隊(duì)列中就不會(huì)出現(xiàn)這種情況
  • 前面介紹過(guò)Main Dispatch Queue是串行隊(duì)列,你懂的??
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末烘浦,一起剝皮案震驚了整個(gè)濱河市抖坪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌闷叉,老刑警劉巖擦俐,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異握侧,居然都是意外死亡蚯瞧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門品擎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)埋合,“玉大人,你說(shuō)我怎么就攤上這事萄传∩跛蹋” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)振诬。 經(jīng)常有香客問我瓣铣,道長(zhǎng),這世上最難降的妖魔是什么贷揽? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮梦碗,結(jié)果婚禮上禽绪,老公的妹妹穿的比我還像新娘。我一直安慰自己洪规,他們只是感情好印屁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斩例,像睡著了一般雄人。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上念赶,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天础钠,我揣著相機(jī)與錄音,去河邊找鬼叉谜。 笑死旗吁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的停局。 我是一名探鬼主播很钓,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼董栽!你這毒婦竟也來(lái)了码倦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锭碳,失蹤者是張志新(化名)和其女友劉穎袁稽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體工禾,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡运提,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闻葵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片民泵。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖槽畔,靈堂內(nèi)的尸體忽然破棺而出栈妆,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布鳞尔,位于F島的核電站嬉橙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寥假。R本人自食惡果不足惜市框,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糕韧。 院中可真熱鬧枫振,春花似錦、人聲如沸萤彩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)雀扶。三九已至杖小,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愚墓,已是汗流浹背予权。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浪册,地道東北人伟件。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像议经,于是被迫代替她去往敵國(guó)和親斧账。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容