打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【iOS】线程安全的文件读写

前段时间看了一遍GCD(Grand Central Dispatch)多线程,GCD是苹果为多核开发提供的解决方案

多线程最常见的问题就是读写,比如数据库读写,文件读写,读取是共享的,写是互斥,允许多个线程进行读操作,当写文件时,阻止队列中所有其他的线程进入,直到文件写完成

 

本文利用GCD提供的相关API封装(主要有dispatch_barrier_asyncdispatch_asyncdispatch_queue_create)一个线程安全的文件读写类FileManager

注:这里使用的文件读写使用NSFileManager类,在测试过程发现多个线程同时写文件的时候并没有发现异常和报错,经过一番查阅发现,原来NSFileManager本身就是线程安全的,多个线程对文件进行写操作,并不会报异常

下面代码只作为加深GCD的学习,实际开发如果使用NSFileManager并不需要考虑线程安全问题(使用NSFileManager的delegate的时候需要注意,需要自己定义一个实例维护状态,避免与共享实例冲突)

 

 

SGFileManager.h

@interface SGFileManager : NSObject+ (instancetype)shareInstance;- (NSData *)readFile:(NSString *)path;- (void)readFileAsync:(NSString *)path complete:(void (^)(NSData *data))complete;- (BOOL)writeFile:(NSString *)path data:(NSData *)data;- (void)writeFileAsync:(NSString *)path data:(NSData *)data complete:(void (^)(BOOL result))complete;@end

SGFileManager.m

#import "SGFileManager.h"//线程队列名称static char *queueName = "fileManagerQueue";@interface SGFileManager (){    //读写队列    dispatch_queue_t _queue;}@end@implementation SGFileManager+ (instancetype)shareInstance{    static id instance = nil;        static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        instance = [[self alloc] init];    });        return instance;}- (instancetype)init{    if(self = [super init]) {        _queue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);    }    return self;}- (NSData *)readFile:(NSString *)path{    __block NSData *data;    dispatch_sync(_queue, ^{        if([[NSFileManager defaultManager] fileExistsAtPath:path]){            data = [[NSFileManager defaultManager] contentsAtPath:path];        }    });    return data;}- (void)readFileAsync:(NSString *)path complete:(void (^)(NSData *data))complete{    dispatch_async(_queue, ^{        NSData *data = nil;                if([[NSFileManager defaultManager] fileExistsAtPath:path]){            data = [[NSFileManager defaultManager] contentsAtPath:path];        }        if (complete) {            complete(data);        }    });}- (BOOL)writeFile:(NSString *)path data:(NSData *)data{    __block BOOL result = NO;    dispatch_barrier_sync(_queue, ^{        NSFileManager *fileManager = [NSFileManager defaultManager];        if([fileManager fileExistsAtPath:path]){            [fileManager removeItemAtPath:path error:nil];        }                result = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];                        NSLog(@"写文件:");    });    return result;}- (void)writeFileAsync:(NSString *)path data:(NSData *)data complete:(void (^)(BOOL result))complete{    __block BOOL result = NO;    dispatch_barrier_async(_queue, ^{        NSFileManager *fileManager = [NSFileManager defaultManager];        if([fileManager fileExistsAtPath:path]){            [fileManager removeItemAtPath:path error:nil];        }                result = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];                if (complete) {            complete(result);        }    });    }@end

 

使用:

    NSString *documentRoot = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];    NSString *filePath = [documentRoot stringByAppendingPathComponent:@"test.txt"];        [[SGFileManager shareInstance] writeFileAsync:filePath data:data complete:^(BOOL result) {        if (result) {            NSLog(@"异步写入文件成功");        }    }];        [[SGFileManager shareInstance] readFileAsync:filePath complete:^(NSData *data) {        if (data) {            NSLog(@"异步读取文件成功");        }    }];

  使用GCD进行多线程开发还是挺方便的,不需要考虑锁的问题,并且性能也比较高,在开发中可以尽量使用GCD进行多线程的开发,并且GCD对从后台到UI的调用也非常方便

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
GCD实战二:资源竞争
iOS的多线程
iPhone文件系统NSFileManager讲解
iOS开发
文件管理2
NSFileManager和NSFileHandle(附:获取文件大小 )
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服