美文网首页
多线层安全的考虑

多线层安全的考虑

作者: Jeff_Kitty | 来源:发表于2017-04-12 14:10 被阅读69次

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

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

对于线程安全,

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.

}

相关文章

  • 多线层安全的考虑

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

  • 深入理解JVM学习笔记-线程安全与锁优化

    线程安全 如果一个对象可以安全的被多个线程同时使用,那他就是线程安全的。当多线程访问一个对象时,如果不同考虑这些线...

  • (165天)《组织的力量》学习笔记009:从洽洽瓜子看第二曲线创

    第二曲线创新分为两层: 第一层是“大创新”,从无到有开拓一条全新的业务线,采用全新的模式实现新的增长。比如,考虑到...

  • 电视

    预算 4000 为线,4000 以上可以考虑国外品牌,4000以下考虑国产品牌。 看电影多,重点考虑黑位、解析度、...

  • 平安平静的日子就是幸福的日子

    小区地下三层车库的积水还没有彻底清理干净。 也许是考虑到安全因素,昨晚开始,负二层的车也停到了负一层,物业员工一直...

  • 2018-08-22雪岩点金:8.22商品期货夜盘策略分析

    能源化工品 【沥青1812】趋势方向形成同向 再次考虑趋势做多。 周线分时来看,均线成排列发散,价格沿均线换上行,...

  • 安全考虑

    翻译原文 date:20170728 按照以往的经验来开发软件通常会比较简单,但是如果用前无古人的方法来写就会有些...

  • 独处时多考虑考虑自己,交往时多考虑考虑别人

    ①我们日常的行为大致可以由两个部分来决定,一个是精神的追求,一个是身体的欲望。这其实就可以解释,为什么有时候明明我...

  • HTTPS浅析

    安全HTTP又称为HTTPS为什么安全呢,因为它在HTTP协议层与TCP层之间又加了一层,传输安全层TLS / S...

  • 可转债的三条安全线

    安全建仓线、安全加仓线和安全重仓线。 它们分别对应到期安全价、回售价、面值。 基本公式如下: (1)到期安全价(又...

网友评论

      本文标题:多线层安全的考虑

      本文链接:https://www.haomeiwen.com/subject/ovwcwttx.html