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

Parser 中GCD的使用(8)

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

    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);
    }
    
    

    总结:使用串行线程来完成加锁操作。

    相关文章

      网友评论

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

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