你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 線程管理的學習記錄

iOS 線程管理的學習記錄

編輯:IOS開發綜合
- (void)method1
{
    NSLog(@%@,NSStringFromSelector(_cmd));
}

- (void)method2
{
    NSLog(@%@,NSStringFromSelector(_cmd));
}

/*
 線程1鎖住之後,線程2會一直等待走到線程1將鎖置為unlock後,才會執行method2方法。
 NSLock是Cocoa提供給我們最基本的鎖對象,這也是我們經常所使用的,除lock和unlock方法外,NSLock還提供了tryLock和lockBeforeDate:兩個方法,前一個方法會嘗試加鎖,如果鎖不可用(已經被鎖住),剛並不會阻塞線程,並返回NO。lockBeforeDate:方法會在所指定Date之前嘗試加鎖,如果在指定時間之前都不能加鎖,則返回NO。
 */
- (IBAction)NSLock:(id)sender {
    
    NSLock *lock = [[NSLock alloc] init];
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [lock lock];
        [self method1];
        sleep(10);
        [lock unlock];
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);//以保證讓線程2的代碼後執行
        [lock lock];
        [self method2];
        [lock unlock];
    });
    
}

/*
 @synchronized指令使用的obj為該鎖的唯一標識,只有當標識相同時,才為滿足互斥,如果線程2中的@synchronized(obj)改為@synchronized(other),剛線程2就不會被阻塞,@synchronized指令實現鎖的優點就是我們不需要在代碼中顯式的創建鎖對象,便可以實現鎖的機制,但作為一種預防措施,@synchronized塊會隱式的添加一個異常處理例程來保護代碼,該處理例程會在異常拋出的時候自動的釋放互斥鎖。所以如果不想讓隱式的異常處理例程帶來額外的開銷,你可以考慮使用鎖對象。
 */
- (IBAction)synchronized:(id)sender {
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(self){
            [self method1];
            sleep(5);
        }
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        @synchronized(self){
            [self method2];
        }
    });
    
}

- (IBAction)pthread_mutex_t:(id)sender {
    
    __block pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, NULL);
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        pthread_mutex_lock(&mutex);
        [self method1];
        sleep(5);
        pthread_mutex_unlock(&mutex);
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        pthread_mutex_lock(&mutex);
        [self method2];
        pthread_mutex_unlock(&mutex);
    });
    
}

- (IBAction)GCD:(id)sender {
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        [self method1];
        sleep(10);
        dispatch_semaphore_signal(semaphore);
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        [self method2];
        dispatch_semaphore_signal(semaphore);
    });
    
}


/*              NSRecursiveLock遞歸鎖
 在線程1中的遞歸block中,鎖會被多次的lock,所以自己也被阻塞了,由於以上的代碼非常的簡短,所以很容易能識別死鎖,但在較為復雜的代碼中,就不那麼容易發現了,那麼如何在遞歸或循環中正確的使用鎖呢?此處的theLock如果換用NSRecursiveLock對象,問題便得到解決了,NSRecursiveLock類定義的鎖可以在同一線程多次lock,而不會造成死鎖。遞歸鎖會跟蹤它被多少次lock。每次成功的lock都必須平衡調用unlock操作。只有所有的鎖住和解鎖操作都平衡的時候,鎖才真正被釋放給其他線程獲得。
 */
- (IBAction)NSRecursiveLock:(id)sender {
    
    NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init];
//    TestObj *obj = [[TestObj alloc] init];
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        static void(^TestMethod)(int);
        TestMethod = ^(int value)
        {
            [theLock lock];
            if (value > 0)
            {
                [self method1];
                sleep(5);
                TestMethod(value-1);
            }
            [theLock unlock];
        };
        
        TestMethod(5);
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(1);
        [theLock lock];
        [self method2];
        [theLock unlock];
    });
    
}

/*              NSConditionLock條件鎖
 在線程1中的加鎖使用了lock,所以是不需要條件的,所以順利的就鎖住了,但在unlock的使用了一個整型的條件,它可以開啟其它線程中正在等待這把鑰匙的臨界地,而線程2則需要一把被標識為2的鑰匙,所以當線程1循環到最後一次的時候,才最終打開了線程2中的阻塞。但即便如此,NSConditionLock也跟其它的鎖一樣,是需要lock與unlock對應的,只是lock,lockWhenCondition:與unlock,unlockWithCondition:是可以隨意組合的,當然這是與你的需求相關的。
 */
- (IBAction)NSConditionLock:(id)sender {
    
    //主線程中
    NSConditionLock *theLock = [[NSConditionLock alloc] init];
    
    //線程1
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0;i<=2;i++)
        {
            [theLock lock];
            NSLog(@thread1:%d,i);
            sleep(2);
            [theLock unlockWithCondition:i];
        }
    });
    
    //線程2
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [theLock lockWhenCondition:2];
        NSLog(@thread2);
        [theLock unlock];
    });
    
}

 

今天發現了非常好的線程管理的文章,特此貼出來學習一下,最後還有一塊並沒有試驗,再次也貼出來,大家可以參考一下

 

NSDistributedLock分布式鎖

以上所有的鎖都是在解決多線程之間的沖突,但如果遇上多個進程或多個程序之間需要構建互斥的情景該怎麼辦呢?這個時候我們就需要使用到NSDistributedLock了,從它的類名就知道這是一個分布式的Lock,NSDistributedLock的實現是通過文件系統的,所以使用它才可以有效的實現不同進程之間的互斥,但NSDistributedLock並非繼承於NSLock,它沒有lock方法,它只實現了tryLock,unlock,breakLock,所以如果需要lock的話,你就必須自己實現一個tryLock的輪詢,下面通過代碼簡單的演示一下吧

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    lock = [[NSDistributedLock alloc] initWithPath:@/Users/mac/Desktop/earning__];
    [lock breakLock];
    [lock tryLock];
    sleep(10);
    [lock unlock];
    NSLog(@appA: OK);
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        lock = [[NSDistributedLock alloc] initWithPath:@/Users/mac/Desktop/earning__];
 
        while (![lock tryLock]) {
            NSLog(@appB: waiting);
            sleep(1);
        }
        [lock unlock];
        NSLog(@appB: OK);
    });

 

先運行程序A,然後立即運行程序B,根據打印你可以清楚的發現,當程序A剛運行的時候,程序B一直處於等待中,當大概10秒過後,程序B便打印出了appB:OK的輸出,以上便實現了兩上不同程序之間的互斥。/Users/mac/Desktop/earning__是一個文件或文件夾的地址,如果該文件或文件夾不存在,那麼在tryLock返回YES時,會自動創建該文件/文件夾。在結束的時候該文件/文件夾會被清除,所以在選擇的該路徑的時候,應該選擇一個不存在的路徑,以防止誤刪了文件。

 

個人覺得除了這些以外,之前還在工作當中用到過一個關於NSTimer的線程管理,那就是timer的暫停和繼續,在此也貼出代碼
 

 

//為NSTimer添加一個分類

#import TFTimer.h


#import 



@interface NSTimer (TFAddition)



-(void)pauseTimer;
-(void)resumeTimer;

@end




#import TFTimer.h


@implementation NSTimer (TFAddition)


-(void)pauseTimer{

if (![self isValid]) {
return ;
}

[self setFireDate:[NSDate distantFuture]]; //如果給我一個期限,我希望是4001-01-01 00:00:00 +0000


}


-(void)resumeTimer{

if (![self isValid]) {
return ;
}

//[self setFireDate:[NSDate dateWithTimeIntervalSinceNow:0]];
[self setFireDate:[NSDate date]];

}

@end

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved