前段时间看了一遍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. java模拟开锁

    java模拟开锁 service qq:928900200 Introduction to Computer Science II: CSCI142Fall 2014Lab #1Instructor: ...

  2. 获取枚举类型的描述description

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...

  3. ECShop 添加文章时作者默认为当前登录用户

    打开admin\article.php文件 查找代码 $article['is_open'] = 1; 在下边添加代码 $article['author'] = $_SESSION['admin_na ...

  4. Asp.net Core中使用NLog,并封装成公共的日志方法

    1.安装NLog "NLog.Extensions.Logging": "1.0.0-rtm-alpha4" 2.配置NLog public void Conf ...

  5. C#代理那点事儿

    Func代理是啥? Func代理接收0个或多个参数,返回TResult值: 以Func<TSource, TResult>为例:Func带来封装一个方法,该方法接收一个参数,然会一个TRe ...

  6. Exists 比Contains 慢非常多。

    void Main() { List<string> s = new List<string>(){}; for(int i=0;i<10000;i++) { s.Add ...

  7. VS2012文本编辑器鼠标不能滚动

  8. AD10长方形通孔焊盘的画法

    1.点击工具栏中[放置焊盘]按钮 2.按键盘Tab键弹出[焊盘]对话框 3.设置[空洞信息]相关尺寸(根据自己所需实际设置) 这里左边的单选按钮选择“槽”,通孔尺寸输入20mil,长度为80mil,旋 ...

  9. js 事件捕获与事件冒泡例子

    http://codepen.io/huashiyiqike/pen/qZVdag addEventListener 默认是冒泡阶段执行,也就是父亲与子都监听时,点击子,子先处理,父亲再处理,这时加s ...

  10. 自动SPF生成工具

    到openspf网站去自动生成一下,地址是http://old.openspf.org/wizard.html.详细解释见下图关于spf的详细语法请看http://www.openspf.org/SP ...