PFMultiProcessFileLockController.m
多进程,文件锁控制器
// 并发队列
_synchronizationQueue = dispatch_queue_create("com.parse.multiprocesslock.controller", DISPATCH_QUEUE_CONCURRENT);
// 屏障 独写
- (void)beginLockedContentAccessForFileAtPath:(NSString *)filePath {
dispatch_barrier_sync(_synchronizationQueue, ^{
PFMultiProcessFileLock *fileLock = self->_locksDictionary[filePath];
if (!fileLock) {
fileLock = [PFMultiProcessFileLock lockForFileWithPath:filePath];
self->_locksDictionary[filePath] = fileLock;
}
[fileLock lock];
NSUInteger contentAccess = [self->_contentAccessDictionary[filePath] unsignedIntegerValue];
self->_contentAccessDictionary[filePath] = @(contentAccess + 1);
});
}
// 屏障 独写
- (void)endLockedContentAccessForFileAtPath:(NSString *)filePath {
dispatch_barrier_sync(_synchronizationQueue, ^{
PFMultiProcessFileLock *fileLock = self->_locksDictionary[filePath];
[fileLock unlock];
if (fileLock && [self->_contentAccessDictionary[filePath] unsignedIntegerValue] == 0) {
[self->_locksDictionary removeObjectForKey:filePath];
[self->_contentAccessDictionary removeObjectForKey:filePath];
}
});
}
// 并发同步,多读
- (NSUInteger)lockedContentAccessCountForFileAtPath:(NSString *)filePath {
__block NSUInteger value = 0;
dispatch_sync(_synchronizationQueue, ^{
value = [self->_contentAccessDictionary[filePath] unsignedIntegerValue];
});
return value;
}
总结:并发屏障,根据需求,独写,并发同步多读。
PFMultiProcessFileLock
自定义文件锁,通过串行 队列来实现, 实现NSLocking 协议,lock 时打开文件,dealloc 时关闭文件。
// 串行队列
- (instancetype)initForFileWithPath:(NSString *)path {
self = [super init];
if (!self) return nil;
_filePath = [path copy];
_lockFilePath = [path stringByAppendingPathExtension:@"pflock"];
NSString *queueName = [NSString stringWithFormat:@"com.parse.multiprocess.%@", path.lastPathComponent.stringByDeletingPathExtension];
_synchronizationQueue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
return self;
}
- (void)dealloc {
[self unlock];
}
// 打开文件
- (void)lock {
dispatch_sync(_synchronizationQueue, ^{
// Greater than zero means that the lock was already succesfully acquired.
if (self->_fileDescriptor > 0) {
return;
}
BOOL locked = NO;
while (!locked) @autoreleasepool {
locked = [self _tryLock];
if (!locked) {
[NSThread sleepForTimeInterval:PFMultiProcessLockAttemptsDelay];
}
}
});
}
// 关闭文件
- (void)unlock {
dispatch_sync(_synchronizationQueue, ^{
// Only descriptor that is greater than zero is going to be open.
if (self->_fileDescriptor <= 0) {
return;
}
close(self->_fileDescriptor);
self->_fileDescriptor = 0;
});
}
// 打开文件
- (BOOL)_tryLock {
const char *filePath = self.lockFilePath.fileSystemRepresentation;
// Atomically create a lock file if it doesn't exist and acquire the lock.
self->_fileDescriptor = open(filePath, (O_RDWR | O_CREAT | O_EXLOCK),
((S_IRUSR | S_IWUSR | S_IXUSR) | (S_IRGRP | S_IWGRP | S_IXGRP) | (S_IROTH | S_IWOTH | S_IXOTH)));
return (self->_fileDescriptor > 0);
}
总结:使用串行线程来完成加锁操作。
网友评论