iOS线程安全数组

iOS-SDK只提供了非线程安全的数组。如果要多线程并发的使用一个数组对象就必须要加锁,平凡的加锁使得代码的调用非常的麻烦。我们需要多线程的读写锁在类的内部实现,所以需要对NSMutableArray进行封装,封装后的对象负责接受所有事件并将其转发给真正的NSMutableArray

 

iOS-SDK只提供了非线程安全的数组。如果要多线程并发的使用一个数组对象就必须要加锁,平凡的加锁使得代码的调用非常的麻烦。

我们需要多线程的读写锁在类的内部实现,所以需要对NSMutableArray进行封装,封装后的对象负责接受所有事件并将其转发给真正的NSMutableArray对象,并通过合理的调度使得其支持多线程并发。

1 新建一个对象来对NSMutableArray 数组进行封装,包含

dispatch_queue_t 调度队列对象 和一个 

NSObject 具体操作对象作为成员变量

      
      
  1. @interface JXMultiThreadObject : NSObject 
  2.     dispatch_queue_t _dispatchQueue; 
  3.     NSObject *_container; 
  4. @property (nonatomic, strong) NSObject *container; 
  5. @end 
 

我们再新建JXMutableArray类继承自JXMultiThreadObject并为其声明简单接口来支持其作为Array使用

      
      
  1. @protocol JXMutableArrayProtocol  
  2. @optional 
  3. - (id)lastObject; 
  4. - (id)objectAtIndex:(NSUInteger)index; 
  5.  
  6. - (NSUInteger)count; 
  7.  
  8. - (void)addObject:(id)anObject; 
  9. - (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 
  10. - (void)removeLastObject; 
  11. - (void)removeObjectAtIndex:(NSUInteger)index; 
  12. - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 
  13. @end 
  14. @interface JXMutableArray : JXMultiThreadObject <JXMutableArrayProtocol> 
 

并且初始化操作对象

      
      
  1. - (id)init 
  2.     self = [super init]; 
  3.     if (self) { 
  4.         self.container = [NSMutableArray array]; 
  5.     } 
  6.     return self; 

2.回到JXMultiThreadObject类中 利用下面方法对一个对象无法实现的方法进行拦截和派发

      
      
  1. - (void)forwardInvocation:(NSInvocation *)anInvocation 
 

该方法当你调用了一个对象没有实现的方法时,forwardInvocation方法将会响应,并让你觉得这个方法的处理方式,

在这之前你需要先实现

      
      
  1. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 
  2.     return [[_container class] instanceMethodSignatureForSelector:aSelector]; 

才能激活forwardInvocation

3.这里利用到G-C-D的调度机制对对象和对象的行为进行调度

      
      
  1. - (void)forwardInvocation:(NSInvocation *)anInvocation 
  2.     dispatch_barrier_sync(_dispatchQueue, ^{ 
  3.         [anInvocation invokeWithTarget:_container]; 
  4.     }); 
 

这里使用了同步的阻塞调度,属于效率比较低的一种调度方式,可以简单地作一下优化

      
      
  1. - (void)forwardInvocation:(NSInvocation *)anInvocation 
  2.     NSMethodSignature *sig = [anInvocation valueForKey:@"_signature"]; 
  3.     const char *returnType = sig.methodReturnType; 
  4.     if (!strcmp(returnType, "v")) { 
  5.         dispatch_barrier_async(_dispatchQueue, ^{ 
  6.             [anInvocation invokeWithTarget:_container]; 
  7.         }); 
  8.     } 
  9.     else { 
  10.         dispatch_barrier_sync(_dispatchQueue, ^{ 
  11.             [anInvocation invokeWithTarget:_container]; 
  12.         }); 
  13.     } 
 

获取调度方法的返回值,如果是void型方法则使用异步调度,如果是getter类型的则使用同步调度,可以略微的提升性能。

你可以通过继承等方法为不同类型的container指定不同的调度规则以确保在逻辑正常的情况下拥有最高的性能。

 

最后附个DEMO的例子https://github.com/joexi/JXMultiThreadObject.git


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值