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

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

本文利用GCD提供的相关API封装(主要有dispatch_barrier_async,dispatch_async,dispatch_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的调用也非常方便

【iOS】线程安全的文件读写的更多相关文章

  1. ios 简单的plist文件读写操作(Document和NSUserDefaults)

    最近遇到ios上文件读写操作的有关知识,记录下来,以便以后查阅,同时分享与大家. 一,简单介绍一下常用的plist文件. 全名是:Property List,属性列表文件,它是一种用来存储串行化后的对 ...

  2. iOS数据持久化文件读写之偏好设置

    很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能.每个应用都有个NSUserDefaults实例,通过它来存取偏好设置.比如, ...

  3. Cocos2d-x在win32,android和IOS下的文件读写问题

    最近在学习和使用Cocos2d-x框架,虽然说的是跨平台,但是在用VS进行开发,然后移植到android或IOS下,也可能会出现各种问题,需要做细微的调整. 例如我在做文件读写操作的时候,很可能在wi ...

  4. ios本地文件内容读取,.json .plist 文件读写

    ios本地文件内容读取,.json .plist 文件读写 本地文件.json .plist文件是较为常用的存储本地数据的文件,对这些文件的操作也是一种常用的基础. 本文同时提供初始化变量的比较标准的 ...

  5. iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像

    iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像 本文档基于H.264的解码,介绍读写Video Toolbox解码回调函数参数CVImag ...

  6. iOS 线程安全

    线程安全: 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.就好比几个人在同一时修改同一个表格,造成数据的错乱. 解决多线程安全问题的方法 方法一:互斥锁(同步锁) @synchroni ...

  7. 实现iOS图片等资源文件的热更新化(三):动态的资源文件夹

    简介 此文,将尝试动态从某个不确定的文件夹中加载资源文件.文章,会继续完善自定义的 imageNamed 函数,并为下一篇文章铺垫. 这么做的意义 正如我们经常所说的那样,大多数情景知道做事的意义往往 ...

  8. (转)linux文件读写的流程

    转自http://hi.baidu.com/_kouu/item/4e9db87580328244ef1e53d0 在<linux内核虚拟文件系统浅析>这篇文章中,我们看到文件是如何被打开 ...

  9. C++文件读写详解(ofstream,ifstream,fstream)

    C++文件读写详解(ofstream,ifstream,fstream) 这里主要是讨论fstream的内容: #include <fstream> ofstream //文件写操作 内存 ...

随机推荐

  1. icmp,tcp,traceroute,ping,iptables

    有东莞的监控主机到北京BGP出问题了: 报警短信疯狂发送: 找东莞IDC和北京BGP服务商协查: 有个奇怪的问题:北京到东莞trcaceroute都有路由信息 东莞143段到北京全无路由信息:但,东莞 ...

  2. Creating Apps With Material Design —— Creating Lists and Cards

    转载请注明 http://blog.csdn.net/eclipsexys 翻译自Developer Android.时间仓促,有翻译问题请留言指出,谢谢 创建Lisst和Cards 在你的应用程序创 ...

  3. vs多项目模板及add-in开发

    本文分2部分 第一为自定义多项目模板 第二为vs add-in开发 效果图 1.自定义模板 2. 工具菜单 3.窗口 4.工程 5.文件 ... 一. 多项目模板 单项目模板做起来很简单 选中一个项目 ...

  4. hive报lzo Premature EOF from inputStream错误

    今天dw组同事发邮件说有一个问题让帮解决一下.他们自己没能搞得定.下面问题解决过程: 1.hql insert overwrite table mds_prod_silent_atten_user p ...

  5. GCC 编译使用动态链接库 LD

    可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig 2.把当前路径加入环境变量LD_LIBRARY_PATH中3. 如果你觉得不会引 ...

  6. Office 2013 Excel 转换 Word

    最新文章:Virson's Blog 参考文章:百度百科 1.使用Excel打开需要转换的Excel文档: 2.采用另存为*.htm的方式将该Excel文档另存为网页,如下图: 3.找到保存的htm网 ...

  7. POJ 2083 Fractal

    Fractal Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6646   Accepted: 3297 Descripti ...

  8. Version of SQLCE in WP8

    The version on the device is compatible with version 3.5 on the desktop, but the Windows Phone versi ...

  9. CSS3实现倒计时

    CSS3实现倒计时小程序,界面如下: 代码如下: <style> body,html{ margin:0px; height:100%; } body{background: #000; ...

  10. SQL SERVER 使用select和union插入多条数据

    insert into A(A) select '2' union select '3' union select '100' go select * from A