国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

IOS 線程鎖

2019-11-08 00:05:07
字體:
來源:轉載
供稿:網友

一、atomic介紹

    在iOS中,@PRoperty 新增屬性時,可以增加atomic選項,atomic會給對應對setter方法加鎖,相當于

 - (void)setTestStr:(NSString *)testStr{    @synchronizad(lock){        if (testStr != _testStr) {            [_testStr release];            _testStr = [testStr retain];        }    }    }

       那么就有問題了,為什么atomic又不是線程安全的呢??而且還會代理性能問題,比起nonatomic性能可能要大減20倍,如果頻繁的調用,可能更多。

       1、當線程A,給TestStr設置值得時候,會調用對應的setter方法,也就是加鎖了,此時B線程也要對TestStr進行設置新值,因為A線程已經鎖住了,所以B只能等待,這個時候是線程安全的。

       2、當線程A,給TestStr設置值得時候,此時B線程在讀TestStr的值,因為setter和getter方法是沒有聯系的,這時,A在執行到加鎖,只是還沒有設置值,然而B線程已經讀取走了,本來是想讀取A設置之后的值,卻讀取了設置之前的值,也就線程不安全了。

       3、當線程A,給TestStr設置值得時候,C線程在A之前release了TestStr,此時就會導致崩潰,也就是線程不安全了。

      總的來說,atomic只是保證了setter方法的安全,沒有保證對應成員變量的多線程安全,所以不是真正的線程安全。

   

二、線程安全的辦法

2.1、synchronizad 給需要加鎖的代碼進行加鎖。

- (IBAction)synchronizad:(id)sender {        FDLog(@"synchronizad 測試");        static NSObject *lock = nil;        if (!lock) {        lock = [[NSString alloc] init];            }    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程A,準備好");        @synchronized(lock){            FDLog(@"線程A lock, 請等待");            [NSThread sleepForTimeInterval:3];            FDLog(@"線程A 執行完畢");        }    });        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程B,準備好");        @synchronized(lock){            FDLog(@"線程B lock, 請等待");            [NSThread sleepForTimeInterval:1];            FDLog(@"線程B 執行完畢");        }    });}

上面的AB線程都使用了同一把鎖,對相應代碼進行加鎖,所以鎖內的代碼是線程安全的。

 

2.2、NSLook 對多線程需要安全的代碼加鎖

- (IBAction)NSLook:(id)sender {    static NSLock *lock = nil;    if (!lock) {        lock = [[NSLock alloc] init];    }        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程A,準備好");        [lock lock];            FDLog(@"線程A lock, 請等待");            [NSThread sleepForTimeInterval:3];            FDLog(@"線程A 執行完畢");        [lock unlock];            });        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程B,準備好");        [lock lock];            FDLog(@"線程B lock, 請等待");            [NSThread sleepForTimeInterval:1];            FDLog(@"線程B 執行完畢");        [lock unlock];    });    }上面的AB線程都使用了同一把鎖,對相應代碼進行加鎖,所以鎖內的代碼是線程安全的。

 

2.3、NSCondition 條件鎖,只有達到條件之后,才會執行鎖操作,否則不會對數據進行加鎖

- (IBAction)NSCondition:(id)sender {#define kCondition_A  1#define kCondition_B  2    __block NSUInteger condition = kCondition_B;    static NSConditionLock *conditionLock = nil;    if (!conditionLock) {        conditionLock = [[NSConditionLock alloc] initWithCondition:condition];    }        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程A,準備好,檢測是否可以加鎖");        BOOL canLock = [conditionLock tryLockWhenCondition:kCondition_A];                if (canLock) {            FDLog(@"線程A lock, 請等待");            [NSThread sleepForTimeInterval:1];            FDLog(@"線程A 執行完畢");            [conditionLock unlock];        }else{            FDLog(@"線程A 條件不滿足,未加lock");        }    });        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        FDLog(@"線程B,準備好,檢測是否可以加鎖");        BOOL canLock = [conditionLock tryLockWhenCondition:kCondition_B];                if (canLock) {            FDLog(@"線程B lock, 請等待");            [NSThread sleepForTimeInterval:1];            FDLog(@"線程B 執行完畢");            [conditionLock unlock];        }else{            FDLog(@"線程B 未加lock");        }    });}

 

2.4、NSRecursiveLock 遞歸鎖,同一個線程可以多次加鎖,但是不會引起死鎖,如果是NSLock,則會導致崩潰

- (void)reverseDebug:(NSUInteger )num lock:(NSRecursiveLock *)lock{    [lock lock];    if (num<=0) {        FDLog(@"結束");        return;    }    FDLog(@"加了遞歸鎖, num = %ld", num);    [NSThread sleepForTimeInterval:0.5];    [self reverseDebug:num-1 lock:lock];        [lock unlock];}- (IBAction)NSRecursiveLock:(id)sender {        static NSRecursiveLock *lock = nil;        if (!lock) {        lock = [[NSRecursiveLock alloc] init];    }        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        [self reverseDebug:5 lock:lock];    });}


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湛江市| 习水县| 兰考县| 木里| 高青县| 日土县| 凤城市| 平陆县| 拉孜县| 义乌市| 松阳县| 尼木县| 衡阳县| 武安市| 隆子县| 云林县| 武汉市| 伊吾县| 英德市| 淳化县| 三江| 井陉县| 安义县| 乌恰县| 饶阳县| 开平市| 荔浦县| 长寿区| 衡阳市| 新竹市| 涪陵区| 宁远县| 扬州市| 宁陕县| 铅山县| 蓝田县| 于田县| 望城县| 醴陵市| 嘉定区| 天津市|