美文网首页
让非线程安全的类变得线程安全

让非线程安全的类变得线程安全

作者: yok_ | 来源:发表于2018-04-11 16:24 被阅读183次

    iOS中有一些类在多线程下操作是不安全的,比如我们常使用的可变类型:NSMutableArray,NSMutableDictnory,NSMutableString...,我们可以通过CGD对这些类进行构建,使这些类在多线程下的操作达到安全的目的。

    使用同步串行队列构建

    @interface LockArray : NSObject
    @property (nonatomic,readonly,assign) NSUInteger count;
    - (id)objectAtIndex:(NSUInteger)index;
    - (NSEnumerator *)objectEnumerator;
    
    - (void)addObject:(id)anObject;
    - (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
    
    - (void)removeObjectAtIndex:(NSUInteger)index;
    - (void)removeLastObject;
    
    - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
    - (NSUInteger)indexOfObject:(id)anObject;
    @end
    
    #import "LockArray.h"
    
    @interface LockArray ()
    @property (nonatomic, strong) NSMutableArray *array;
    
    @property (nonatomic, strong) dispatch_queue_t dispatchQueue;
    
    @end
    @implementation LockArray
    - (instancetype)init{
        if (self) {
            NSString* queueid = [NSString stringWithFormat:@"com.lock.array_%p", self];
            _dispatchQueue = dispatch_queue_create([queueid UTF8String], DISPATCH_QUEUE_SERIAL);
            _array = [NSMutableArray array];
        }
        return self;
    }
    
    -(NSUInteger)count
    {
        __block NSUInteger count;
        dispatch_sync(_dispatchQueue, ^{
            count = _array.count;
        });
        return count;
    }
    
    - (id)objectAtIndex:(NSUInteger)index{
        __block id obj;
        dispatch_sync(_dispatchQueue, ^{
            if (index < [_array count]) {
                obj = _array[index];
            }
        });
        return obj;
    }
    
    - (NSEnumerator *)objectEnumerator{
        __block NSEnumerator *enu;
        dispatch_sync(_dispatchQueue, ^{
            enu = [_array objectEnumerator];
        });
        return enu;
    }
    
    - (void)insertObject:(id)anObject atIndex:(NSUInteger)index{
        dispatch_sync(_dispatchQueue, ^{
            if (anObject && index < [_array count]) {
                [_array insertObject:anObject atIndex:index];
            }
        });
        
    }
    
    - (void)addObject:(id)anObject{
        dispatch_sync(_dispatchQueue, ^{
            if(anObject){
                [_array addObject:anObject];
            }
        });
    }
    
    - (void)removeObjectAtIndex:(NSUInteger)index{
        dispatch_sync(_dispatchQueue, ^{
            if (index < [_array count]) {
                [_array removeObjectAtIndex:index];
            }
        });
    }
    
    - (void)removeLastObject{
        dispatch_sync(_dispatchQueue, ^{
            [_array removeLastObject];
    
        });
    }
    
    - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject{
        dispatch_sync(_dispatchQueue, ^{
            if (anObject && index < [_array count]) {
                [_array replaceObjectAtIndex:index withObject:anObject];
            }
        });
    }
    
    - (NSUInteger)indexOfObject:(id)anObject{
        
        __block NSUInteger index = NSNotFound;
        dispatch_sync(_dispatchQueue, ^{
            for (int i = 0; i < [_array count]; i ++) {
                if ([_array objectAtIndex:i] == anObject) {
                    index = i;
                    break;
                }
            }
        });
        
        return index;
    }
    
    - (void)dealloc{
        if (_dispatchQueue) {
            _dispatchQueue = NULL;
        }
    }
    @end
    

    同步串行队列虽然可以达到线程安全的目的,但效率没那么高,如果能将同步与异步派发结合起来,实现与普通加锁机制一样的同步行为,又不会阻塞执行异步派发的线程,效率会比单纯的同步要好

    并发队列结合栅栏块

    当我们进行读的操作时使用同步执行,当进行写的操作时使用异步栅栏

    @interface HLockArray : NSObject
    @property (nonatomic,readonly,assign) NSUInteger count;
    - (id)objectAtIndex:(NSUInteger)index;
    - (NSEnumerator *)objectEnumerator;
    
    - (void)addObject:(id)anObject;
    - (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
    
    - (void)removeObjectAtIndex:(NSUInteger)index;
    - (void)removeLastObject;
    
    - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
    - (NSUInteger)indexOfObject:(id)anObject;
    @end
    
    @interface HLockArray ()
    @property (nonatomic, strong) NSMutableArray *array;
    
    @property (nonatomic, strong) dispatch_queue_t dispatchQueue;
    @end
    @implementation HLockArray
    - (instancetype)init{
        if (self) {
            NSString* queueid = [NSString stringWithFormat:@"com.lock.array_%p", self];
            _dispatchQueue = dispatch_queue_create([queueid UTF8String], DISPATCH_QUEUE_SERIAL);
            _array = [NSMutableArray array];
        }
        return self;
    }
    
    - (NSUInteger)count{
        __block NSUInteger count;
        dispatch_sync(_dispatchQueue, ^{
            count = _array.count;
        });
        return count;
    }
    
    - (id)objectAtIndex:(NSUInteger)index{
        __block id obj;
        dispatch_sync(_dispatchQueue, ^{
            if (index < [_array count]) {
                obj = _array[index];
            }
        });
        return obj;
    }
    
    - (NSEnumerator *)objectEnumerator{
        __block NSEnumerator *enu;
        dispatch_sync(_dispatchQueue, ^{
            enu = [_array objectEnumerator];
        });
        return enu;
    }
    
    - (void)insertObject:(id)anObject atIndex:(NSUInteger)index{
        dispatch_barrier_async(_dispatchQueue, ^{
            if (anObject && index < [_array count]) {
                [_array insertObject:anObject atIndex:index];
            }
        });
    }
    
    - (void)addObject:(id)anObject{
        dispatch_barrier_async(_dispatchQueue, ^{
            if(anObject){
                [_array addObject:anObject];
            }
        });
    }
    
    - (void)removeObjectAtIndex:(NSUInteger)index{
        dispatch_barrier_async(_dispatchQueue, ^{
            
            if (index < [_array count]) {
                [_array removeObjectAtIndex:index];
            }
        });
    }
    
    - (void)removeLastObject{
        dispatch_barrier_async(_dispatchQueue, ^{
            [_array removeLastObject];
        });
    }
    
    - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject{
        dispatch_barrier_async(_dispatchQueue, ^{
            if (anObject && index < [_array count]) {
                [_array replaceObjectAtIndex:index withObject:anObject];
            }
        });
    }
    
    - (NSUInteger)indexOfObject:(id)anObject{
        __block NSUInteger index = NSNotFound;
        dispatch_sync(_dispatchQueue, ^{
            for (int i = 0; i < [_array count]; i ++) {
                if ([_array objectAtIndex:i] == anObject) {
                    index = i;
                    break;
                }
            }
        });
        return index;
    }
    
    - (void)dealloc{
        if (_dispatchQueue) {
            _dispatchQueue = NULL;
        }
    }
    

    参考文章:
    Cocoa线程安全/非线程安全的类和函数汇总
    大牛们是如何构建一个线程安全的字典的!
    关于NSMutableArray线程安全的思考和实现

    相关文章

      网友评论

          本文标题:让非线程安全的类变得线程安全

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