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

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

作者: 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线程安全的思考和实现

相关文章

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

    iOS中有一些类在多线程下操作是不安全的,比如我们常使用的可变类型:NSMutableArray,NSMutabl...

  • JAVA 线程安全

    线程安全定义 一个类在可以被多个线程安全调用时就是线程安全的。 线程安全分类 线程安全不是一个非真即假的命题,可以...

  • 多线程之线程安全性

    多线程环境下使用非线程安全类会导致线程安全问题。线程安全问题表现为原子性,有序性,可见性 在讲述线程安全三大特性之...

  • 【设计模式】单例模式

    定义 确保某个类只有一个实例 实现方式 饿汉式加载(线程安全) 等价于 懒汉式加载 非线程安全 线程安全 Doub...

  • HashMap深入解析

    兄弟姐妹 HashMap:快,遍历顺序不确定,非线程安全Hashtable:遗留类,线程安全,只有一个线程能写,并...

  • StringBuffer、Stringbuilder线程安全之源

    想必大家都知道StringBuffer 为线程安全类,StringBuilder为非线程安全,但是 是否有过究其原...

  • 12 并发安全

    1 类的线程安全定义。怎么才能做到类的线程安全? 类的线程安全定义如果多线程下使用这个类,不过多线程如何使用和调度...

  • String、StringBuffer、StringBuilde

    String 是字符串常量(线程安全);StringBuffer(线程安全), StringBuilder(非线程...

  • 2.1synchronized同步方法

    “线程安全”与“非线程安全”相关的技术点,它们是学习多线程技术时一定会遇到的经典问题。“非线程安全”其实会在多个线...

  • ConcurrentHashMap浅析

    简述 ConcurrentHashMap是针对HashMap非线程安全和HashTable低性能线程安全。它是线程...

网友评论

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

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