多线层安全的考虑

对于多线层的安全一直都是面试的重点,面试官一般会问线程安全,你会从那些角度去解决这个问题?

这里我说一下我的拙见,如果有更好的还请补充,不喜勿喷,谢谢!

对于线程安全,

1.首先可以使用noatomic,使用这个属性就会对该属性的setter方法加锁,这样的话可以保证线程的安全,但是失去了多线层的优势;

2.使用线程锁来保证同时只有一个线程能对数组进行写操作;

3.使用串行队列保证线程安全;

4.使用dispatch_notify来保证线程的执行顺序;

5.使用dipatch_barrier些操作和dispatch_asyn读操作;

首先看一段代码:

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-1");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-2");

});

dispatch_barrier_async(concurrentQueue, ^(){

NSLog(@"dispatch-barrier");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-3");

});

dispatch_async(concurrentQueue, ^(){

NSLog(@"dispatch-4");

});

这里dispatch_barrier的方法会在他之前的子线层dispatch_async执行完毕后再去执行,等到dispatch_barrier执行完成后,就恢复原来的操作,其实这里我们可以在dispatch_async方法里面进行读操作,然后再dispatch_barrier里面进行写操作,这样就可以保证线程安全以及利用多线层的优势了;

可变数组NSMuatbleArray是线程安全的吗?

下面咱们来看一下NSMutableArray线程安全的实现

1 继承 NSMutableArray创建NSKSafeMutableArray在这个地方遇到了一些坑通过查阅文档发现问题所在:

在 Cocoa 中有一种奇葩的类存在 Class Clusters。面向对象的编程告诉我们:“类可以继承,子类具有父类的方法”。而 Cocoa 中的 Class Clusters 虽然平时表现的像普通类一样,但子类却没法继承父类的方法。 NSMutableArray就是这样的存在。为什么会这样呢?因为 Class Clusters 内部其实是由多个私有的类和方法组成。虽然它有这样的弊端,但是好处还是不言而喻的。例如,NSNumber 其实也是这种类,这样一个类可以把各种不同的原始类型封装到一个类下面,提供统一的接口。这正设计模式中的抽象工厂模式。

查看Apple的文档,要继承这样的类需要必须实现其primitive methods方法,实现了这些方法,其它方法便都能通过这些方法组合而成。比如需要继承NSMutableArray就需要实现它的以下primitive methods:- (void)addObject:(id)anObject;- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;- (void)removeLastObject;- (void)removeObjectAtIndex:(NSUInteger)index;- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;1234512345和NSArray的primitive methods:- (NSUInteger)count;- (id)objectAtIndex:(NSUInteger)index;12122 NSKSafeMutableArray.h 的实现如下#import "NSKSafeMutableArray.h"@interface NSKSafeMutableArray(){    CFMutableArrayRef _array;}@end@implementation NSKSafeMutableArray- (id)init{    return [self initWithCapacity:10];}- (id)initWithCapacity:(NSUInteger)numItems{    self = [super init];    if (self)    {        _array = CFArrayCreateMutable(kCFAllocatorDefault, numItems,  &kCFTypeArrayCallBacks);    }    return self;}- (NSUInteger)count {    __block NSUInteger result;    dispatch_sync(self.syncQueue, ^{        result = CFArrayGetCount(_array);    });    return result;}- (id)objectAtIndex:(NSUInteger)index {    __block id result;    dispatch_sync(self.syncQueue, ^{        NSUInteger count = CFArrayGetCount(_array);        result = indexcount) {

blockindex = count;

}

CFArrayInsertValueAtIndex(_array, index, (__bridge const void *)anObject);

});

}

- (void)removeObjectAtIndex:(NSUInteger)index

{

dispatch_barrier_async(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

NSLog(@"count:%lu,index:%lu",(unsigned long)count,(unsigned long)index);

if (index < count) {

CFArrayRemoveValueAtIndex(_array, index);

}

});

}

- (void)addObject:(id)anObject

{

dispatch_barrier_async(self.syncQueue, ^{

if (!anObject)

return;

CFArrayAppendValue(_array, (__bridge const void *)anObject);

});

}

- (void)removeLastObject {

dispatch_barrier_async(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

if (count > 0) {

CFArrayRemoveValueAtIndex(_array, count-1);

}

});

}

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {

dispatch_barrier_async(self.syncQueue, ^{

if (!anObject)

return;

NSUInteger count = CFArrayGetCount(_array);

CFArraySetValueAtIndex(_array, index, (__bridge const void*)anObject);

});

}

#pragma mark Optional

- (void)removeAllObjects

{

dispatch_barrier_async(self.syncQueue, ^{

CFArrayRemoveAllValues(_array);

});

}

- (NSUInteger)indexOfObject:(id)anObject{

if (!anObject)

return NSNotFound;

__block NSUInteger result;

dispatch_sync(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

result = CFArrayGetFirstIndexOfValue(_array, CFRangeMake(0, count), (__bridge const void *)(anObject));

});

return result;

return result;

}

#pragma mark - Private

- (dispatch_queue_t)syncQueue {

static dispatch_queue_t queue = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

queue = dispatch_queue_create("com.kong.NSKSafeMutableArray", DISPATCH_QUEUE_CONCURRENT);

});

return queue;

}

@end

3 调用

- (void)viewDidLoad {

[super viewDidLoad];

NSKSafeMutableArray *safeArr = [[NSKSafeMutableArray alloc] init];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

for ( int i = 0; i < 5; i ++) {

dispatch_async(queue, ^{

NSLog(@"添加第%d个",i);

[safeArr addObject:[NSString stringWithFormat:@"%d",i]];

});

dispatch_async(queue, ^{

NSLog(@"删除第%d个",i);

[safeArr removeObjectAtIndex:i];

});

}

// Do any additional setup after loading the view, typically from a nib.

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • 同步/异步 同步:多个任务情况下,一个任务A执行结束,才可以执行另一个任务B。只存在一个线程也就是主线程。 异步:...
    XLsn0w阅读 302评论 0 0
  • 今天表姐跟我说: 我婆婆要给你介绍一个对象。他是大学生,在城里有房,镇里也有房。她说,村里的女孩子都不给她们介绍,...
    春天的野林子阅读 221评论 0 0
  • 归来多日,阅读朋友们的行走随笔,高手如云,我更不敢写了,连涂鸦兄都说群里高人众多,一篇篇地读下去,自愧不如,这差距...
    自强不息678阅读 385评论 0 0
  • 翻阅着自己亲手写过的一篇篇有爱有生活的温暖字眼,滚烫的泪珠再也没忍住。我想,我再也写不出来那些洋溢幸福的画面,...
    Danny0阅读 191评论 0 0
  • 有没有那么一个人, 虽不在你身边, 却又好像就在身畔; 有没有那么一个人, 虽久未谋面, 却又好像仿若昨天; 有没...
    橙星辰阅读 242评论 0 0