iOS開發之Run Loop

1、概述編程

(1) Run Loop提供了一種異步執行代碼的機制,不能並行執行任務。網絡

(2) 在主隊列中,Main Run Loop直接配合任務的執行,負責處理UI事件、計時器,以及其它內核相關事件。多線程

(3) Run Loop的主要目的是保證程序執行的線程不會被系統終止。併發

Run Loop的工做特色:異步

(1) 當有事件發生時,Run Loop會根據具體的事件類型通知應用程序作出響應。async

(2) 當沒有事件發生時,Run Loop會進入休眠狀態,從而達到省電的目的。oop

(3) 當事件再次發生時,Run Loop會被從新喚醒,處理事件。性能

主線程和其餘線程中的Run Loopatom

iOS程序的主線程默認已經配置好了Run Loop,其餘線程默認狀況下沒有設置Run Loop。spa

通常在開發中不多會主動建立RunLoop,而一般會把事件添加到RunLoop中。

loop示意圖:

2UIApplication中的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 性能消耗很是的大,蘋果官方不建議使用。

在實際開發中,不要去搶奪資源!

*** 併發編程最主要的目的是提升性能,讓更多的代碼同時運行,達到併發運行,提升總體性能的目的!

*** 手機開發最主要的是流暢,並行,至於資源搶奪的功能開發是屬於服務端的範疇!

相關文章
相關標籤/搜索