iOS的读写安全方案

Atmotic

atomic 只能保证set和get方法内线程安全,比如objc.arry 点语法是安全的,但是[objc.array addObject:someOne]是不安全的。非常耗性能,一般只在Mac上使用。

atomic在源码中相关部分。

static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
    if (offset == 0) {
        object_setClass(self, newValue);
        return;
    }
    id oldValue;
    id *slot = (id*) ((char*)self + offset);
    if (copy) {
        newValue = [newValue copyWithZone:nil];
    } else if (mutableCopy) {
        newValue = [newValue mutableCopyWithZone:nil];
    } else {
        if (*slot == newValue) return;
        newValue = objc_retain(newValue);
    }
    if (!atomic) {
        oldValue = *slot;
        *slot = newValue;
    } else {
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock();
        oldValue = *slot;
        *slot = newValue;        
        slotlock.unlock();
    }
    objc_release(oldValue);
}
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (offset == 0) {
        return object_getClass(self);
    }

    // Retain release world
    id *slot = (id*) ((char*)self + offset);
    if (!atomic) return *slot;
        
    // Atomic retain release world
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();
    id value = objc_retain(*slot);
    slotlock.unlock();
    
    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    return objc_autoreleaseReturnValue(value);
}

IO操作,文件操作(读取,写入)
传统意义上的锁无法满足文件读写的需求,因为读取需要很多个线程可以同时进行,而写入只能有一个线程,但是如果只给写入文件的操作加锁的话,线程又不安全。
pthread_rwlock_t 就满足了我们的需求。

pthread_rwlock_t lock;
pthread_rwlock_init(&_lock,NULL);//初始化
//pthread_rw_tryrdlock(&lock);读_尝试加锁
//pthread_rwlock_trywrlock(&lock);写尝试加锁
//pthread_rwlock_destroy(&lock)// 销毁锁
//读取文件的锁,当有文件在写入时,必须等待写入文件完成
pthread_rwlock_rdlock(&_lock);//读加锁
NSLog(@"%s", __func__);
pthread_rwlock_unlock(&_lock);
//写入文件加锁,无需等待读取文件的操作
pthread_rwlock_wrlock(&_lock);//写加锁
NSLog(@"%s", __func__); 
pthread_rwlock_unlock(&_lock);//解锁

dispatch_barrier_async

使用dispatch_barrier_async同样可以解决读写问题,dispatch_barrier_async可以保证在一个队列里,当执行dispatch_barrier_async里面的任务时,其他任务都会停止。实现多读单写需求。

- (void)barrierAsync_rwTest
{
    _queue = dispatch_queue_create("rwQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i<5; i++) {
        [[[NSThread alloc]initWithTarget:self selector:@selector(barrier_read) object:nil]start];
        [[[NSThread alloc]initWithTarget:self selector:@selector(barrier_write) object:nil]start];
    }
}
- (void)barrier_read{
    dispatch_async(_queue, ^{
        NSLog(@"%s",__func__);
    });
}

- (void)barrier_write{
    //必须保证是自己创建的b并发队列
    //一旦开始写,队列里的其他任务都不能进行
    dispatch_barrier_async(_queue, ^{
      NSLog(@"%s",__func__);
    });
}

你可能感兴趣的:(iOS的读写安全方案)