多線程01 pthread NSThread 多線程的資源共享問題-鎖

凡是跟UI相關(guān)的都是在主線程執(zhí)行的

UIKit類庫的線程都是不安全的 所以我們需要在主線程上更新UI 因此主線程又叫UI線程

多線程的核心思想 : 就是把耗時操作放在后臺執(zhí)行,避免耗時操作卡死UI

currentThread : 查看當(dāng)前線程

NSLog(@"%@",[NSThread currentThread]);

同步和異步

同步和異步是任務(wù) / 代碼 執(zhí)行的兩種方式

同步--->多個任務(wù)按順序依次執(zhí)行,就是同步執(zhí)行

異步--->多個任務(wù)同時執(zhí)行,就是異步執(zhí)行

pthread

參數(shù)1 : 子線程的ID / 標(biāo)識

在C語言中,一般帶`_t` / `_ref`標(biāo)識數(shù)據(jù)類型

參數(shù)2 : 子線程的屬性,一般傳NULL

NULL : 表示空地址,一般在C語言使用;

nil : 表示空對象,一般在OC使用;

其實,NULLh和nil本質(zhì)上沒有半點兒區(qū)別

參數(shù)3 : 子線程需要執(zhí)行的函數(shù)

void *(*)(void *) : 表示指向函數(shù)的指針,即函數(shù)名;函數(shù)名就是表示函數(shù)地址;

數(shù)組地址就是數(shù)組名或者數(shù)組第0個角標(biāo)元素的地址

void * 表示可以指向任何地址的指針,代表任意數(shù)據(jù)類型;類似于OC的id;

返回值? ? 函數(shù)名? ? 函數(shù)參數(shù)

void *? ? (*)? ? (void *)

參數(shù)4 : 傳入到子線程需要執(zhí)行的函數(shù)的參數(shù)

返回值 : int;在很多C語言框架中,并不是遵守非零既真;因為成功的結(jié)果只有一個,0是唯一的;失敗的原因有很多;

線程調(diào)試 : 查看方法執(zhí)行的線程是否是主線程或者子線程

{number = 1, name = main} : 表示主線程

{number = 3, name = (null)} : 只要number != 1 就表示子線程

提示 : 千萬不要糾結(jié)number到底等于幾,系統(tǒng)分配的

// 參數(shù)1

pthread_t ID;

// 創(chuàng)建了一個子線程,執(zhí)行demo函數(shù)

int result = pthread_create(&ID, NULL, demo, NULL);

// 判斷創(chuàng)建子線程是否成功

if (result == 0) {

NSLog(@"創(chuàng)建子線程成功");

} else {

NSLog(@"創(chuàng)建子線程失敗");

}

子線程執(zhí)行的函數(shù)

*/

void *demo(void *param)

{

NSString *str = (__bridge NSString *)(param);

// currentThread : 查看當(dāng)前線程

NSLog(@"demo %@ - %@",[NSThread currentThread],str);

return NULL;

}


NSThread創(chuàng)建線程三種方式


[self performSelectorInBackground:@selector(demo:) withObject:@"perform"];

以上參數(shù)介紹:

1.NSObject分類方法創(chuàng)建子線程

2.不可以拿到線程對象

3.不需要手動啟動線程


[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"detach"];

以上參數(shù)介紹:

1.類方法創(chuàng)建子線程

2.不可以拿到線程對象

3.不需要手動啟動線程


// 創(chuàng)建線程對象

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"alloc"];

// 啟動線程

[thread start];

以上參數(shù)介紹:

1.構(gòu)造方法創(chuàng)建子線程

2.可以拿到線程對象

3.需要手動啟動線程


通知主線程刷新UI

// waitUntilDone : 是否等待updateUI執(zhí)行完,再執(zhí)行后面的代碼,一般傳入NO

[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO];


關(guān)于以上使用調(diào)用方法中-target和selector關(guān)系

@selector中需要傳入一個方法

而target中需要傳入對象告訴系統(tǒng) 這個方法是哪個對象的


線程的聲明周期

提示 : 程序員只能做新建和就緒,其他的都由系統(tǒng)來處理

// 創(chuàng)建線程對象 : 新建狀態(tài)

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];

// 啟動線程 : 就緒狀態(tài)(把線程對象添加到可調(diào)度線程池,等待被CPU調(diào)度執(zhí)行)

[thread start];

// sleepForTimeInterval : 使當(dāng)前線程休眠到指定時長

[NSThread sleepForTimeInterval:1.0];

// sleepUntilDate : 使當(dāng)前線程休眠到指定日期

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

// 使當(dāng)前線程強制死亡

[NSThread exit];


線程的屬性

//新建狀態(tài)

NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];

// 設(shè)置線程對象的name屬性 : 標(biāo)識一個唯一的線程對象,方便跟蹤

thread1.name = @"t1";

thread1.threadPriority = 1.0;

// 設(shè)置線程對象的優(yōu)先級 : 浮點數(shù);范圍是0.0~1.0;最高是1.0;默認是0.5

// 線程優(yōu)先級不能決定線程執(zhí)行的先后順序,只能決定某個線程有更多的機會被CPU先調(diào)度執(zhí)行完,概率事件

// 注意 : 實際開發(fā)中,千萬不要設(shè)置優(yōu)先級或者服務(wù)器質(zhì)量,會出現(xiàn)意想不到的問題;使用默認的,讓系統(tǒng)自己來處理

// threadPriority : 在目前即將被廢棄,使用qualityOfService來替代;

thread1.qualityOfService = NSQualityOfServiceUserInteractive;

// stackSize : 線程占用內(nèi)存空間大小

NSLog(@"子 %tu",[NSThread currentThread].stackSize / 1024);


多線程的資源共享問題

// 互斥鎖 / 同步鎖 : 使用了線程同步技術(shù)

// 特點 : 可以保證被鎖定的代碼,同一時間只有一個線程可以訪問

// self : 表示互斥鎖的參數(shù);互斥鎖的參數(shù),又叫做鎖對象;

// 鎖對象 : 任何繼承自NSObject的對象,都可以作為互斥鎖的參數(shù);內(nèi)部有把鎖,默認是開啟的

// 鎖對象必須是全局的對象;self是最方便獲取的全局的鎖對象

// 局部鎖對象是鎖不住的,因為每次線程進來之前會新建一把鎖

// 提示 : 加鎖的事情,不是再客戶端操作的;是服務(wù)器加鎖的,多線程資源共享絕大多數(shù)是在服務(wù)器發(fā)生;

// 提示 : 加鎖是犧牲了性能,保證安全.客戶端的性能不能輕易犧牲

@synchronized (self)

{

? ? ? //需要被鎖定的代碼

}

參數(shù)必須傳全局對象 多數(shù)傳self?


原子屬性

使用nonatomic修飾的屬性為非原子屬性

使用atomic修飾的屬性為原子屬性

原子屬性 : 單寫多讀

單寫多讀 : 同一時間只有一個線程可以訪問setter方法;但是可以有多個線程訪問getter方法

注意 : 原子屬性的setter方法是線程安全的,getter方法是線程非安全的

setter方法內(nèi)部有把自旋鎖


自旋鎖 :

?看不見的,由系統(tǒng)封裝的

可以保證被鎖定的代碼,同一時間只能有一個線程可以訪問

一旦外面的線程,發(fā)現(xiàn)代碼被自旋鎖鎖定,外面的線程會以死循環(huán)的方式等待開鎖

互斥鎖 :

可以保證被鎖定的代碼,同一時間只能有一個線程可以訪問

一旦外面的線程,發(fā)現(xiàn)代碼被互斥鎖鎖定,外面的線程會進入就緒狀態(tài),等待開鎖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、多線程基礎(chǔ) 基本概念 進程進程是指在系統(tǒng)中正在運行的一個應(yīng)用程序每個進程之間是獨立的,每個進程均運行在其專用且...
    AlanGe閱讀 651評論 0 0
  • 多線程基本概念 單核CPU,同一時間cpu只能處理1個線程,只有1個線程在執(zhí)行 。多線程同時執(zhí)行:是CPU快速的在...
    WeiHing閱讀 786評論 1 5
  • 一個人的所有問題,都存在于他的身體里面,他的基本問題,就是他害怕自己“復(fù)活”,體驗到豐富的情緒。 我們不得不面對一...
    明瑩閱讀 291評論 0 0
  • 你的眼睛透著一幅畫, 特別、神秘、深邃 時而蜷縮在椅子上, 引著鼻煙,恍若時人 時而...
    呆兜閱讀 240評論 0 3
  • 作為一個90后,星爺?shù)狞S金時代似乎離我,我們很遠,只是淺淺記得小時電影頻道一遍遍重播的懷舊電影《功夫之王》,卻...
    Secretes閱讀 269評論 0 2

友情鏈接更多精彩內(nèi)容