多线程异步安全,安全锁的问题

本篇文章主要介绍多线程在异步时候的内部代码调用。以及加锁时候代码的调用。比较明显的使用地点是数据库操作。资源竞争。
首先我们常用到的锁有以下几种:

@synchronizad、atomic、NSLook、NSRecursiveLock(递归锁)



接下来先逐一简单介绍一下这些个线程锁:

1. @synchronizad

这个是常规的局部代码锁。使用方式:

@synchronized(lock){

     A代码
}
@synchronized(lock){

     B代码
}    

lock 是id类型,只要求唯一性就可以。通常用self即可

加密后相当于队列效果,执行完A之后才会执行B。即便是两个异步线程。

2.aotomic

这个属于属性锁,也就是原子操作。一个@property使用了这个关键字之后,他的setter方法会自动枷锁。加锁方式用的就是@synchronizad。 但是这个属性不要随便乱用,第一他的性能消耗太高,是noaotomic的20倍差不多。而且,仅仅对setter方法加锁是有漏洞的,具体例子就是读取和set的顺序问题。

3.NSLook

有点类似于@synchronized 保证多线程代码安全

 lock = [[NSLock alloc] init];

[lock lock];

代码块

[lock unlock];    
4.NSCondition

条件锁,只有达到条件之后,才会执行锁操作

BOOL canLock = [conditionLock tryLockWhenCondition:condition];
5.NSRecursiveLock

递归锁主要防止崩溃,一个代码块里多次加锁

比如:自身调用自身加锁。

下面介绍一下多线程中加锁:先贴几行代码:


- (void)testLock{
    
    __block NSString *name = @"000";
    static NSString *staName = @"staticName";
    
    ///常规代码锁
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"线程A,准备好");
        name = @"11";
        @synchronized(name){
            NSLog(@"线程A lock, 请等待");
            [NSThread sleepForTimeInterval:5];
            name = @"111";
            staName = @"static111";
           
            //如果判断语句为false,报错
            NSCAssert([name isEqualToString:@"111"], @"前面的值错误了,不满足条件");
            NSLog(@"线程A 执行完毕  %@  %@",name,staName);
        }
        
    });
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"线程B,准备好");
        name = @"22";
        @synchronized(name){
            NSLog(@"线程B lock, 请等待");
            [NSThread sleepForTimeInterval:2];
            name = @"222";
            staName = @"static222";
            NSLog(@"线程B 执行完毕  %@  %@",name,staName);
        }
    });
}

正常情况下,不加任何锁,那么线程A和线程B的执行顺序是随机的。
加了线程锁以后,再测试调用一下:

for (int i = 0; i<10; i++) {
        [self testLock];
        sleep(20);
    }


结论:
1.异步线程中加锁 可以转化异步线程同步线程,保证唯一性
2.如果不加锁,那么A和B的执行顺序是随机的, AB内部的代码执行顺序也是随机的
3.加锁的对象,必须保证唯一不会被随便改变。通常用数据库本身或者self来做加锁对象。单例最好。如果加锁,则AB的执行顺序虽然是随机的,但是遇到锁,B还是会等待A锁内执行完毕再执行B。
注意:如果在A方法中对加锁的对象做出了修改,那么B方法中的加锁将失效。继而变成随机执行


待更新。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,514评论 11 349
  • 前言 iOS开发中由于各种第三方库的高度封装,对锁的使用很少,刚好之前面试中被问到的关于并发编程锁的问题,都是一知...
    喵渣渣阅读 9,154评论 0 33
  • 一、多线程 说明下线程的状态 java中的线程一共有 5 种状态。 NEW:这种情况指的是,通过 New 关键字创...
    Java旅行者阅读 10,202评论 0 44
  • objc中向一个nil对象发送消息会怎么样? 首先明确一点,在OC中对一个nil对象发送消息是有效的,不会有错误 ...
    mdiep阅读 3,459评论 0 7
  • Beer Opening Glass 让您摆脱喝啤酒时到处找开瓶器的烦恼。钢制底部带有开瓶器,既能有保冷作用,又能...
    晶品TRIZ阅读 3,047评论 0 0

友情链接更多精彩内容