前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS读写安全

iOS读写安全

作者头像
老沙
发布2019-09-28 13:19:18
9070
发布2019-09-28 13:19:18
举报
文章被收录于专栏:老沙课堂

所有Demo 都在文章末尾提供下载

锁的用法可以参照上篇文章 Objective-C 加锁:看我就够了!

1、atomic & noatomic

给属性添加atomic 可以保证属性的setter和getter原子性操作,也就是保证setter和getter内部是线程同步的

  • 源码 objc4 objc-accessors.mm文件
代码语言:javascript
复制
//setter方法
void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy)
{
    bool copy = (shouldCopy && shouldCopy != MUTABLE_COPY);
    bool mutableCopy = (shouldCopy == MUTABLE_COPY);
    reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy);
}

static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
...
    if (!atomic) { // 如果非原子性 直接赋值
        oldValue = *slot;
        *slot = newValue;
    } else { //如果是原子性,加自旋锁
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock();
        oldValue = *slot;
        *slot = newValue;
        slotlock.unlock();
    }
...
}
// getter方法
  id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
   ...
    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);
}
复制代码
  • 从源码看 atomic是自旋锁,且只能保证在Setter和getter的时候安全,例如[NSMutableArray addobject]的时候 是不安全的

2、读写锁

为什么会有读写锁,用其他的的锁来实现不可以么?

普通锁可以达到同一时间段只有一个线程对本地文件进行读或者写。效率低。无法保证read的时候可以多线程read,而只是在write的时候 只有一个线程在write。

所以 pthread_rwlock解决这个问题。可以达到 当线程write的时候,只有一个线程写入。read的时候可以多线程read。

  • API:
代码语言:javascript
复制
#import <pthread.h>
pthread_rwlock_init(&_lock, NULL);
pthread_rwlock_rdlock(&_lock); //read的时候用的锁
pthread_rwlock_wrlock(&_lock);// write的时候用的锁
pthread_rwlock_unlock(&_lock);
pthread_rwlock_tryrdlock(pthread_rwlock_t *) //尝试read锁
pthread_rwlock_trywrlock(pthread_rwlock_t *) //尝试wirte锁
复制代码
  • 举个?
代码语言:javascript
复制
#import <pthread.h>

- (void)viewDidLoad {
    [super viewDidLoad];
    pthread_rwlock_init(&_lock, NULL);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    dispatch_queue_t queue = dispatch_queue_create("rwqueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i ++) {
        dispatch_async(queue, ^{
            for (int i = 0; i < 10; i ++) {
                [self read];
            }
        });
        
        dispatch_async(queue, ^{
            for (int i = 0; i < 10; i ++) {
                [self read];
            }
        });
        
        dispatch_async(queue, ^{
            [self write];
        });
    }
}

- (void) read {
    pthread_rwlock_rdlock(&_lock);
    sleep(1);
    NSLog(@"read");
    pthread_rwlock_unlock(&_lock);
}

- (void) write {
    pthread_rwlock_wrlock(&_lock);
    sleep(1);
    NSLog(@"write");
    pthread_rwlock_unlock(&_lock);
}
复制代码
  • 运行结果及分析:

3、dispatch_barrier_async

举个?

代码语言:javascript
复制
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    _queue = dispatch_queue_create("rwqueue", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i < 10; i ++) {
        [self read];
        [self write];
        [self write];
        [self read];
    }
    
}

- (void) read {
    dispatch_async(_queue, ^{
        sleep(1);
        NSLog(@"read");
    });
}

- (void) write {
    dispatch_barrier_async(_queue, ^{
        sleep(1);
        NSLog(@"write");
    });
}
复制代码
  • 运行结果分析
  • 注意点 必须传入dispatch_queue_create的并发队列 不能传入dispatch_get_global_queue队列 如果传入串行或者是global 就相当于dispatch_async ,没有栅栏(barrier)效果
  • 原理
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老沙说点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、atomic & noatomic
  • 2、读写锁
  • 3、dispatch_barrier_async
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档