美文网首页iOS DeveloperiOS进阶指南
iOS 线程安全之@synchronized同步锁

iOS 线程安全之@synchronized同步锁

作者: 迷路的安然和无恙 | 来源:发表于2017-08-19 22:48 被阅读478次
//  先看问题
- (NSString *)xua {
    if (!_xua) {
        @synchronized (_xua) {
            if (!_xua) {
                _xua = [TAFManager XUA];
            }
        }
    }
    return _xua;
}

这段代码有什么问题吗?为了保持线程同步,需要给对象加锁。对@synchronized: 防止不同的线程同时执行同一段代码。

结果

上面的线程会存在_xuanil的情况(第一次获取值的时候),当被锁定的对象为nil时,其实@synchronized是无作用的,也就是不能保证线程安全。

原理

我对 @synchronized的实现十分好奇并搜了一些它的细节。我找到了一些答案,但这些解释都没有达到我想要的深度。锁是如何与你传入 @synchronized 的对象关联上的?@synchronized会保持(retain,增加引用计数)被锁住的对象么?假如你传入 @synchronized 的对象在 @synchronizedblock里面被释放或者被赋值为 nil 将会怎么样?这些全都是我想回答的问题。而我这次的收获,会要你好看。
@synchronized 的文档告诉我们, @synchronized block 在被保护的代码上暗中添加了一个异常处理。为的是同步某对象时如若抛出异常,锁会被释放掉。@synchronized block 会变成 objc_sync_enterobjc_sync_exit的成对儿调用。我们不知道这些函数是干啥的,但基于这些事实我们可以认为编译器将这样的代码:

@synchronized(obj) {
    // do work
}
转化成这样的东东
@try {
    objc_sync_enter(obj);
    // do work
} @finally {
    objc_sync_exit(obj);    
}

objc_sync_enter 和 objc_sync_exit 是啥?它们是如何实现的?在 Xcode 中按住 Command 键单击它们,然后进到了,里面有我们感兴趣的这两个函数:

/** 
 * Begin synchronizing on 'obj'.  
 * Allocates recursive pthread_mutex associated with 'obj' if needed.
 * 
 * @param obj The object to begin synchronizing on.
 * 
 * @return OBJC_SYNC_SUCCESS once lock is acquired.  
 */
OBJC_EXPORT int
objc_sync_enter(id _Nonnull obj)
    OBJC_AVAILABLE(10.3, 2.0, 9.0, 1.0, 2.0);

/** 
 * End synchronizing on 'obj'. 
 * 
 * @param obj The object to end synchronizing on.
 * 
 * @return OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
 */
OBJC_EXPORT int
objc_sync_exit(id _Nonnull obj)
    OBJC_AVAILABLE(10.3, 2.0, 9.0, 1.0, 2.0);

不过,objc_sync_enter的文档告诉我们一些新东西: @synchronized 结构在工作时为传入的对象分配了一个递归锁。分配工作何时发生,如何发生呢?它怎样处理 nil?幸运的是 Objective-C runtime 是开源的,所以我们可以马上阅读源码并找到答案!

注:递归锁在被同一线程重复获取时不会产生死锁。
想深入了解,有个叫做 NSRecursiveLock 的现成的类也是这样的,你可以试试。
你可以在这里找到 objc-sync 的全部源码。

相关文章

  • OC--各种线程锁

    参考:正确使用多线程同步锁@synchronized()iOS中的锁iOS多线程安全详解iOS 常见知识点(三):...

  • Synchronized

    1.synchronized同步线程安全锁

  • iOS 线程安全之@synchronized同步锁

    这段代码有什么问题吗?为了保持线程同步,需要给对象加锁。对@synchronized: 防止不同的线程同时执行同一...

  • 同步锁Lock

    用于解决多线程安全问题的方式:synchronized 隐式锁 同步代码块 同步方法 jdk1.5后新增 同步锁...

  • iOS开发中常用的锁

    锁是线程编程同步工具的基础,在iOS开发中常用的锁有以下几种: @synchronized NSLock 对象锁 ...

  • 使用乐观锁优化并行操作

    Synchronized 和 Lock 实现的同步锁机制,这两种同步锁都属于悲观锁,是保护线程安全最直观的方式。悲...

  • 多线程之volatile

    volatile Synchronized 同步锁给多个线程访问的代码块加锁以保证线程安全性。多线程之Synchr...

  • 线程的基本语法

    线程同步[解决线程安全问题] 解决线程安全问题 线程同步方式一:同步代码 语法基本 synchronized (同...

  • 起底多线程同步锁(iOS)

    起底多线程同步锁(iOS) 起底多线程同步锁(iOS)

  • 多线程资源共享之同步锁

    本篇为大家讲解解决多线程线程安全问题的另一种思路,同步锁:synchronized和ReentrantLock。...

网友评论

    本文标题:iOS 线程安全之@synchronized同步锁

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