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];
}
...
}
总结:
- 数据保护的方式
- @synchronized( object), @synchronized(self.changeVar)
- NSLock
- 串行队列的使用
- dispatch_once
网友评论