IOS NSLocking协议,NSLock,NSConditionLock,NSRecursiveLock,NSCondition

来源:互联网 发布:网络音箱哪个牌子好 编辑:程序博客网 时间:2024/05/01 07:06

NSLocking 有两个方法

// 上锁- (void)lock;// 解锁- (void)unlock;

实现协议的对象都具有 上锁和解锁功能,NSLock,NSConditionLock,NSRecursiveLock,NSCondition
NSLock
在多线程开发的环境下,多个线程运作的时候NSLock 就会显得特别重要!
NSLock 就是锁定,解锁。

    NSLock * lock = [[NSLock alloc]init];    NSMutableArray * piaos = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];    // 线程1        dispatch_async(dispatch_get_global_queue(0, 0), ^{            [lock lock];            NSString * st = piaos[0];            NSLog(@"++%@",st);            sleep(3);            [piaos removeObject:@"1"];            [lock unlock];        });    // 线程2        dispatch_async(dispatch_get_global_queue(0, 0), ^{            NSLog(@"xxoo");        });   // 线程3        dispatch_async(dispatch_get_global_queue(0, 0), ^{            [lock lock];            NSLog(@"%@",piaos);            [lock unlock];        });

上面有3个线程 其中有两个线程加锁。一个没加锁,运行以后你会发现

2015-12-25 17:21:01.770 Nsthirth[3385:2053566] ++12015-12-25 17:21:01.770 Nsthirth[3385:2053468] xxoo2015-12-25 17:21:04.771 Nsthirth[3385:2053471] (    2,    3)

线程2 开线程以后就开始跑了6666,线程1 和3 加了锁 线程1先一步锁定,线程3就需要等待3S 才执行
这里要说点小主意NSLock 加锁的时紧跟着lock 后免得语句

dispatch_async(dispatch_get_global_queue(0, 0), ^{        NSLog(@"%@",piaos);        [lock lock];        [lock unlock];    });2015-12-25 17:24:10.537 Nsthirth[3398:2066640] xxoo2015-12-25 17:24:10.537 Nsthirth[3398:2066639] ++12015-12-25 17:24:10.537 Nsthirth[3398:2066624] (    1,    2,    3)

这样就没延迟执行的意思!
就是lock 这个加锁 执行 ,解锁执行。就是这个对象所有锁定的执行代码 只能一个一个的解锁执行!
NSConditionLock 条件锁在一定条件上锁。解锁。

- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER;@property (readonly) NSInteger condition;// 上锁在一定条件下 参数是个NSInteger- (void)lockWhenCondition:(NSInteger)condition;// 尝试上锁 返回一个BOOL- (BOOL)tryLock;- (BOOL)tryLockWhenCondition:(NSInteger)condition;// 解锁在一定条件下 参数是个NSInteger- (void)unlockWithCondition:(NSInteger)condition;// 上锁在木一个时间点- (BOOL)lockBeforeDate:(NSDate *)limit;- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;// 标签@property (nullable, copy) NSString *name

直接上代码

    NSConditionLock * lock = [[NSConditionLock alloc]init];    NSMutableArray * piaos = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];    // 线程1        dispatch_async(dispatch_get_global_queue(0, 0), ^{            for (int i = 0; i< piaos.count; i++) {                [lock lock];                NSLog(@"哎呀哦");                [lock unlockWithCondition:i];                sleep(3);            }        });    // 线程2        dispatch_async(dispatch_get_global_queue(0, 0), ^{            [lock lockWhenCondition:2];            NSLog(@"xxoo");            [lock unlock];        });2015-12-25 17:46:31.678 Nsthirth[3465:2153031] 哎呀哦2015-12-25 17:46:34.684 Nsthirth[3465:2153031] 哎呀哦2015-12-25 17:46:37.688 Nsthirth[3465:2153031] 哎呀哦2015-12-25 17:46:37.688 Nsthirth[3465:2153028] xxoo

lock , lockWhenCondition,unlock,unlockWithCondition 可以随意组合

NSRecursiveLock 递归加锁
平时我们在代码中使用锁的时候,最容易犯的一个错误就是造成死锁,而容易造成死锁的一种情形就是在递归或循环中,如下代码:

NSRecursiveLock *lock = [[NSRecursiveLock alloc]init];    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        static void (^RecursiveMethod)(int);        RecursiveMethod = ^(int value) {            [lock lock];            if (value > 0) {                NSLog(@"value = %d", value);                sleep(2);                RecursiveMethod(value - 1);            }            [lock unlock];        };        RecursiveMethod(10);    });

NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得
NSCondition 条件

- (void)wait;- (BOOL)waitUntilDate:(NSDate *)limit;- (void)signal;- (void)broadcast

下面代码是不满足条件暂停, 满足 继续走!

NSCondition * lock = [[NSCondition alloc]init];    NSMutableArray * piaos = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];    // 线程1        dispatch_async(dispatch_get_global_queue(0, 0), ^{            [lock lock];            NSLog(@"&&&&&");            if (piaos.count>0) {                [lock wait];                NSLog(@"还没处理完!");            }            [lock unlock];        });    // 线程2        dispatch_async(dispatch_get_global_queue(0, 0), ^{            static void (^clearTheObj)(NSMutableArray * array);            clearTheObj = ^(NSMutableArray * array){                NSLog(@"%lu",(unsigned long)array.count);                if ([array count]>0) {                    [array removeObjectAtIndex:0];                }else{                    [lock signal];                    return;                }                sleep(1);                clearTheObj(array);            };            [lock lock];            clearTheObj(piaos);            [lock unlock];        });2015-12-25 18:10:10.580 Nsthirth[3558:2272749] &&&&&2015-12-25 18:10:10.581 Nsthirth[3558:2272750] 32015-12-25 18:10:11.583 Nsthirth[3558:2272750] 22015-12-25 18:10:12.586 Nsthirth[3558:2272750] 12015-12-25 18:10:13.589 Nsthirth[3558:2272750] 02015-12-25 18:10:13.590 Nsthirth[3558:2272749] 还没处理完!

虽然线程1先lock 但是条件不满足 我们暂停线程执行 线程2 当一定条件下我们发表一下通知 线程1继续执行。
NSDistributedLock分布式锁
引用大婶上面的一段总结
以上所有的锁都是在解决多线程之间的冲突,但如果遇上多个进程或多个程序之间需要构建互斥的情景该怎么办呢?这个时候我们就需要使用到NSDistributedLock了,从它的类名就知道这是一个分布式的Lock,NSDistributedLock的实现是通过文件系统的,所以使用它才可以有效的实现不同进程之间的互斥,但NSDistributedLock并非继承于NSLock,它没有lock方法,它只实现了tryLock,unlock,breakLock,所以如果需要lock的话,你就必须自己实现一个tryLock的轮询,下面通过代码简单的演示一下吧:
程序A

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");});

程序B

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");    });

这应该是多客户端同步吧。。。请轻打脸。。。。

小白总结 很多不对地方请打脸。多谢!

0 0
原创粉丝点击