5. 锁

作者: 算命的李老师 | 来源:发表于2020-09-25 17:45 被阅读0次
    ==1.@synchronize==
    • 用于单例创建,使多线程下保证唯一对象
    • 代码块可用于数组中唯一线程读写
    ==2.atomic==
    • 是对象的属性关键字,负责对象的原子性操作,不负责对象的使用
    • atomic 系统会在生成的setter/getter方法里添加锁,但是这个锁仅仅是保证了setter/getter存取的安全,并不能保证数据结果正确
    • A、B、C等多个线程都要操作同一个对象setter,D线程要getter这个对象的值,那么每个线程都成保证各自数据的完整性,但是D线程最后get到的值并不能确定。
    ==3.OSSpinlock==
    自旋锁

    循环等待访问,不释放当前资源,类似while(1),负责轻量级的+1,-1,如在引用计数的+1,-1操作

    ==4.NSRecursiveLock==
    递归锁

    为了解决NSLock在已加锁的情况下重复加锁,调用NSRecursiveLock的lock方法,可以使加锁之后仍然获取到锁,并且加锁。加锁解锁成对出现。解决多线程下递归方法的加锁。

    ==4.NSLock==

    线程锁,为了解决线程同步问题

    ==5.dispatch_semaphore_t==

    信号量,实现对线程同步,资源共享访问的信号量级锁

    1.GCD信号量简介
    //和GCD的group等用法一致,这个函数是创建一个dispatch_s`emaphore_类型的信号量
    //并且创建的时候需要指定信号量的大小。
    dispatch_semaphore_create(long value); // 创建信号量
    
    //发送信号量。该函数会对信号量的值进行加1操作。
    dispatch_semaphore_signal(dispatch_semaphore_t deem); // 发送信号量
    
    //等待信号量。如果信号量值为0,那么该函数就会一直等待,也就是不返回(相当于阻塞当前线程)
    //直到该函数等待的信号量的值大于等于1,该函数会对信号量的值进行减1操作,然后返回。
    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信号量
    
    2.用信号量机制使异步线程完成同步操作

    两个任务虽然是异步的,但仍需要同步执行

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        dispatch_group_t grp = dispatch_group_create();
        dispatch_queue_t queue = dispatch_queue_create("concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
        
        dispatch_group_async(grp, queue, ^{
            dispatch_semaphore_t sema = dispatch_semaphore_create(0);
            NSLog(@"task1 begin : %@",[NSThread currentThread]);
            dispatch_async(queue, ^{
                NSLog(@"task1 finish : %@",[NSThread currentThread]);
                dispatch_semaphore_signal(sema);
            });
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            //先等待task1内的信号量 直到 task1 finish
        });
        dispatch_group_async(grp, queue, ^{
            dispatch_semaphore_t sema = dispatch_semaphore_create(0);
            NSLog(@"task2 begin : %@",[NSThread currentThread]);
            dispatch_async(queue, ^{
                NSLog(@"task2 finish : %@",[NSThread currentThread]);
                dispatch_semaphore_signal(sema);
            });
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        });
        dispatch_group_notify(grp, dispatch_get_main_queue(), ^{
            NSLog(@"refresh UI");
        });
    }
    
    3 阻塞请求线程
    dispatch_async(queue, 0), ^{
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        [网络请求:^{
            //请求回调
            dispatch_semaphore_signal(sema);  
        }];
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    });
    //多个请求顺序执行
    
    ==6.dispatch_barrier_async和dispatch_barrier_sync==

    栅栏方法,用GCD方式实现多读单写

    dispatch_barrier_sync

    需要等待栅栏执行完才会执行栅栏后面的任务

    dispatch_barrier_async

    无需等待栅栏执行完,会继续往下走(保留在队列里)

     dispatch_async(queue, ^{
            NSLog(@"----1-----%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----2-----%@", [NSThread currentThread]);
        });
        
        dispatch_barrier_async(queue, ^{
            //会等待内部执行完才往下走
            NSLog(@"----barrier-----%@", [NSThread currentThread]);
        });
        dispatch_barrier_sync(queue, ^{
            //会等待内部执行完才往下走
            NSLog(@"----barrier-----%@", [NSThread currentThread]);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"----3-----%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----4-----%@", [NSThread currentThread]);
        });
    

    线程安全的数组

    • 对元素的获取增加dispatch_sync
    - (id)objectAtIndex:(NSUInteger)index {
       __block id item = nil;
       dispatch_sync(self.readWriteQuene, ^{
           if (index <= self.array.count - 1) {
               item = [self.array objectAtIndex:index];
           }
       });
       return item;
    }
    - (nullable id)getFirstObject {
       __block id item = nil;
       dispatch_sync(self.readWriteQuene, ^{
           if (self.array.count > 0) {
               item = [self.array objectAtIndex:0];
           }
       });
       return item;
    }
    - (nullable id)getLastObject {
       __block id item = nil;
       dispatch_sync(self.readWriteQuene, ^{
           NSUInteger size = self.array.count;
           if (size > 0) {
               item = self.array[size - 1];
           }
       });
       return item;
    }
    
    • 对数组操作增加栅栏方法
    //synchronized 效率最低
    - (void)addObject:(id)anObject {
       dispatch_barrier_async(self.readWriteQuene, ^{
           [self.array addObject:anObject];
       });
    }
    
    - (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
       dispatch_barrier_async(self.readWriteQuene, ^{
           [self.array insertObject:anObject atIndex:index];
       });
    }
    //还有很多操作数组的方法如removeLastObject
    

    相关文章

      网友评论

          本文标题:5. 锁

          本文链接:https://www.haomeiwen.com/subject/cxgfuktx.html