美文网首页
Parser 中GCD的使用(4)

Parser 中GCD的使用(4)

作者: 老猫_2017 | 来源:发表于2020-01-17 10:56 被阅读0次

PFRelation 是映射多对对的关系, 使用串行队列 来保证线程安全。

    
_stateAccessQueue = dispatch_queue_create("com.parse.relation.state.access", DISPATCH_QUEUE_SERIAL);

// 采用串行队列,来保证数据安全。
- (void)setTargetClass:(NSString *)targetClass {
    dispatch_sync(_stateAccessQueue, ^{
        self.state.targetClass = targetClass;
    });
}

- (BOOL)_hasKnownObject:(PFObject *)object {
    __block BOOL results = NO;

    dispatch_sync(_stateAccessQueue, ^{
        results = [self.state.knownObjects containsObject:object];
    });

    return results;
}

PFTaskQueue 数据的加锁🔒操作 @synchronized (self.mutex) 采用对象加锁,来进行数据保护

@property (nonatomic, strong, readwrite) NSObject *mutex;
    
self.mutex = [[NSObject alloc] init];

- (BFTask *)enqueue:(BFTask *(^)(BFTask *toAwait))taskStart {
    @synchronized (self.mutex) {
        BFTask *oldTail = self.tail ?: [BFTask taskWithResult:nil];

        // The task created by taskStart is responsible for waiting on the
        // task passed to it before doing its work. This gives it an opportunity
        // to do startup work or save state before waiting for its turn in the queue.
        BFTask *task = taskStart(oldTail);

        // The tail task should be dependent on the old tail as well as the newly-created
        // task. This prevents cancellation of the new task from causing the queue to run
        // out of order.
        self.tail = [BFTask taskForCompletionOfAllTasks:@[oldTail, task]];

        return task;
    }
}

PFInternalUtils 工具类,加锁使用 NSLock 来进行加锁

+ (NSString *)currentSystemTimeZoneName {
    static NSLock *methodLock;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        methodLock = [[NSLock alloc] init];
    });

    [methodLock lock];
    [NSTimeZone resetSystemTimeZone];
    NSString *systemTimeZoneName = [[NSTimeZone systemTimeZone].name copy];
    [methodLock unlock];

    return systemTimeZoneName;
}

PFLocationManager 定位管理

// 保证主线程执行, 采用 block 封装
+ (CLLocationManager *)_newSystemLocationManager {
    __block CLLocationManager *manager = nil;

    // CLLocationManager should be created only on main thread, as it needs a run loop to serve delegate callbacks
    dispatch_block_t block = ^{
        manager = [[CLLocationManager alloc] init];
    };
    if ([NSThread currentThread].isMainThread) {
        block();
    } else {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
    return manager;
}



- (void)addBlockForCurrentLocation:(PFLocationManagerLocationUpdateBlock)handler {
  //  synchronized 加锁
    @synchronized (self.blockSet) {
        [self.blockSet addObject:[handler copy]];
    }

    //
    // Abandon hope all ye who enter here.
    // Apparently, the CLLocationManager API is different for iOS/OSX/watchOS/tvOS up to the point,
    // where encapsulating pieces together just makes much more sense
    // than hard to human-parse compiled out pieces of the code.
    // This looks duplicated, slightly, but very much intentional.
    //
        ...
    // 保证异步到主线程,进行执行, block 封装调用
    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        dispatch_block_t block = ^{
            if (self.application.applicationState != UIApplicationStateBackground &&
                [self.bundle objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
                [self.locationManager requestWhenInUseAuthorization];
            } else {
                [self.locationManager requestAlwaysAuthorization];
            }
        };
        if ([NSThread currentThread].isMainThread) {
            block();
        } else {
            dispatch_async(dispatch_get_main_queue(), block);
        }
    }
    [self.locationManager startUpdatingLocation];
#elif PF_TARGET_OS_OSX
    [self.locationManager startUpdatingLocation];
#endif
}

// 多线程 保护,数据变更
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    ...
    NSMutableSet *callbacks = [NSMutableSet setWithCapacity:1];
    @synchronized (self.blockSet) {
        [callbacks setSet:self.blockSet];
        [self.blockSet removeAllObjects];
    }
    ...
}

总结:

  1. 数据保护的方式
    • @synchronized( object), @synchronized(self.changeVar)
    • NSLock
    • 串行队列的使用
    • dispatch_once

相关文章

网友评论

      本文标题:Parser 中GCD的使用(4)

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