Parser 中GCD的使用(8)

2020-01-17  本文已影响0人  老猫_2017

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

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

上一篇 下一篇

猜你喜欢

热点阅读