標籤:
1、概述
(1) Run Loop提供了一種非同步執行代碼的機制,不能並存執行任務。
(2) 在主隊列中,Main Run Loop直接配合任務的執行,負責處理UI事件、計時器,以及其它核心相關事件。
(3) Run Loop的主要目的是保證程式執行的線程不會被系統終止。
Run Loop的工作特點:
(1) 當有事件發生時,Run Loop會根據具體的事件類型通知應用程式做出響應。
(2) 當沒有事件發生時,Run Loop會進入休眠狀態,從而達到省電的目的。
(3) 當事件再次發生時,Run Loop會被重新喚醒,處理事件。
主線程和其他線程中的Run Loop:
iOS程式的主線程預設已經配置好了Run Loop,其他線程預設情況下沒有設定Run Loop。
一般在開發中很少會主動建立RunLoop,而通常會把事件添加到RunLoop中。
loop:
2、UIApplication中的Run Loop
3、多線程中的循環參考
如果self對象持有操作對象的引用,同時操作對象當中又直接存取了self時,才會造成循環參考。
單純在操作對象中使用self不會造成循環參考。
注意:此時不能使用(weakSelf)
4、多線程中的資源共用
並發編程中許多問題的根源就是在多線程中訪問共用資源。資源可以是一個屬性、一個對象、網路裝置或者一個檔案等。
在多線程中任何一個共用的資源都可能是一個潛在的衝突點,必須精心設計以防止這種衝突的發生。
資源共用樣本:
5、互斥鎖(@synchronized)
互斥鎖使用注意:
(1)加互斥鎖,在共用資源的“讀”“寫”範圍添加互斥鎖
(2)要讓鎖的範圍儘可能小!
(3)資源搶奪做簡單的做法就是使用互斥鎖@synchronized
(4)使用互斥鎖,會變慢,互斥鎖的代價十分高昂!
加上互斥鎖就可以使一個資源在同一時間只能被一個線程訪問,只有這個資源被這個線程用完後其他線程才能訪問。
互斥鎖用法:
@synchronized(self) {
//線程操作
}
例如:
@interface MJViewController ()
@property (weak, nonatomic) IBOutlet UITextView *infoText;
// 票數,若使用原子鎖,只需在互斥鎖的基礎上把下面nonatomic改為atomic即可
@property (nonatomic, assign) NSInteger tickets;
@end
@implementation MJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
// 賣票迴圈,一直賣完為止
- (void)doSaleLoop:(NSString *)opName
{
// 所有線程進入都可以迴圈賣票
while (YES) {
@synchronized(self) {
if (self.tickets > 0) {
--self.tickets;
NSLog(@"剩餘票數 %d - %@ - %@", self.tickets, opName, [NSThread currentThread]);
} else {
break;
}
}
//-----------------------------------------
// 類比休眠,跟資源搶奪無關,不用放在鎖裡
if ([opName isEqualToString:@"OP 1"]) {
[NSThread sleepForTimeInterval:1.0f];
} else {
[NSThread sleepForTimeInterval:0.3f];
}
}
}
#pragma mark 類比多人賣票
#pragma mark GCD實現
- (IBAction)doSale:(id)sender
{
// 做多線程開始時,永遠不要相信一次啟動並執行結果
self.tickets = 20;
// 1. 隊列
dispatch_queue_t q = dispatch_queue_create("sale", DISPATCH_QUEUE_CONCURRENT);
// 2. 新增工作
dispatch_async(q, ^{
[self doSaleLoop:@"OP 1"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 2"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 3"];
});
dispatch_async(q, ^{
[self doSaleLoop:@"OP 4"];
});
}
@end
【備忘】在iOS中還有一種鎖的功能,原子鎖 —— 多讀單寫的鎖(128位自旋鎖),也會消耗效能。
原子鎖只保護寫入時的資料正確,而讀取不負責。
對於要寫入的資源,保護“寫入資料”的正確性重要,還是讀取的準確性重要!
如果只是開發單寫多讀的功能,只需要使用原子鎖即可。
@synchronized 效能消耗非常的大,蘋果官方不建議使用。
在實際開發中,不要去搶奪資源!
*** 並發編程最主要的目的是提高效能,讓更多的代碼同時運行,達到並發運行,提高整體效能的目的!
*** 手機開發最主要的是流暢,並行,至於資源搶奪的功能開發是屬於服務端的範疇!
iOS開發之Run Loop