MST

星途 面试题库

面试题:Objective-C类初始化时机与机制

在Objective-C运行时中,类的初始化在什么情况下会发生?类的初始化机制是如何保证线程安全的?请详细阐述。
31.6万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

类的初始化发生情况

  1. 首次发送消息:当向类发送第一个消息时,会触发类的初始化。例如,[MyClass new] 或者 [MyClass someClassMethod],此时如果该类尚未初始化,则会进行初始化。
  2. 子类初始化:当一个子类被初始化时,如果其父类还未初始化,那么父类会先被初始化。例如,定义了 SubClass 继承自 SuperClass,在初始化 SubClass 时,若 SuperClass 未初始化,则 SuperClass 会先初始化。
  3. 访问类的非懒加载的静态变量:如果类中定义了非懒加载的静态变量(如 static int myStaticVar;),并且在代码中访问了该变量,也会触发类的初始化。

类的初始化机制保证线程安全的方式

在Objective - C运行时,类的初始化是通过 +load+initialize 方法来实现的,并且这两个方法有着不同的线程安全机制:

  1. +load 方法
    • 调用时机:在程序启动时,运行时系统会根据每个类在编译时的依赖关系,按照继承体系的顺序加载类和分类。每个类的 +load 方法会在其被加载时调用,并且只调用一次。先调用父类的 +load 方法,然后再调用子类的 +load 方法,分类的 +load 方法会在类的 +load 方法之后调用。
    • 线程安全:运行时系统保证 +load 方法在程序启动过程中被调用,并且是在一个线程安全的环境下调用。这意味着多个线程不会同时调用同一个类的 +load 方法,所以开发者不需要额外处理线程安全问题。
  2. +initialize 方法
    • 调用时机+initialize 方法在类或其子类接收到第一条消息之前被调用,并且只调用一次。如果子类没有实现 +initialize 方法,当子类接收到消息时,会调用父类的 +initialize 方法。
    • 线程安全:运行时系统使用锁机制来确保 +initialize 方法的线程安全。在多线程环境下,当一个线程首次尝试调用 +initialize 方法时,会获取锁。如果另一个线程已经在执行 +initialize 方法,其他线程会等待锁的释放。这种机制保证了 +initialize 方法只会被一个线程执行一次,避免了重复初始化的问题。同时,开发者在实现 +initialize 方法时,也需要注意避免死锁等线程相关问题,因为如果在 +initialize 方法中使用锁不当,可能会导致死锁。例如,不要在 +initialize 方法中递归调用 +initialize 方法或者在锁内进行可能导致死锁的操作。