weak的实现原理

其实好多技术我们用的都很多,但是如果展开其中的细节原理,不一定能说的清楚。今天就说一下我们常用的属性修饰词weak

例子

@interface Person : NSObject
@property (nonatomic, strong) Person *friend;
@end@implementation Person
@endint main() {Person *person1 = [[Person alloc] init];Person *person2 = [[Person alloc] init];person1.friend = person2;person2.friend = person1;// 使用 weak 防止循环引用__weak Person *weakPerson = person1;person1 = nil;  // 这里 person1 被释放,weakPerson 自动变为 nilNSLog(@"%@", weakPerson); // 输出:nullreturn 0;
}

在这个例子中,person1person2 之间互相引用。如果我们使用 strong 修饰符,它们会互相持有对方的强引用,从而形成循环引用,导致它们无法释放。但是,当我们将 person1 赋值给 weakPerson 后,weakPerson 不增加 person1 的引用计数,因此当 person1 被置为 nil 时,weakPerson 也会自动被置为 nil

这背后的机制涉及 Side Table 结构和 objc_storeWeakobjc_loadWeak 这两个函数的作用。

核心数据结构

weak 机制主要依赖于两个核心的数据结构:SideTableweak_table_t

1. SideTable

在 Objective - C 运行时中,存在多个 SideTable 实例,这些实例被组织成一个全局的哈希表。每个 SideTable 结构体包含三个主要成员:

struct SideTable {spinlock_t slock;  // 自旋锁,用于保证线程安全RefcountMap refcnts;  // 引用计数表,记录对象的引用计数weak_table_t weak_table;  // 弱引用表,记录对象的弱引用信息
};
2. weak_table_t

weak_table_tSideTable 中的弱引用表,其结构如下:

struct weak_table_t {weak_entry_t *weak_entries;  // 弱引用条目数组size_t    num_entries;  // 弱引用条目数量uintptr_t mask;  // 哈希表的掩码,用于计算哈希索引uintptr_t max_hash_displacement;  // 最大哈希冲突位移
};
  • weak_entries:是一个指向 weak_entry_t 数组的指针,每个 weak_entry_t 记录了一个对象的所有弱引用信息。
  • num_entries:表示当前弱引用条目的数量。
  • mask:用于计算对象在 weak_entries 数组中的哈希索引。
  • max_hash_displacement:记录了在处理哈希冲突时的最大位移量。
3. weak_entry_t

weak_entry_t 结构体用于存储一个对象的所有弱引用信息,其结构如下:

typedef struct weak_entry_t {DisguisedPtr<objc_object> referent;  // 被引用的对象union {struct {weak_referrer_t *referrers;  // 弱引用指针数组uintptr_t        out_of_line_ness : 2;  // 是否使用外部存储标志uintptr_t        num_refs : PTR_MINUS_2;  // 弱引用指针数量uintptr_t        mask;  // 哈希表的掩码,用于计算哈希索引uintptr_t        max_hash_displacement;  // 最大哈希冲突位移};struct {// 内联存储,用于存储少量弱引用weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];};};
} weak_entry_t;
  • referent:是一个伪装指针,指向被引用的对象。
  • referrers:是一个指向 weak_referrer_t 数组的指针,weak_referrer_t 实际上就是 objc_object ** 类型,用于存储所有指向该对象的弱引用指针。
  • num_refs:记录了当前对象的弱引用指针数量。

实现流程

1. 弱引用的创建

当使用 __weak 修饰一个变量并指向一个对象时,会调用 objc_initWeak 函数,该函数的主要流程如下:

  • 检查对象是否为 nil,如果为 nil,则直接将弱引用指针置为 nil
  • 调用 storeWeak 函数,在 SideTable 中查找对应的 weak_table_t,并在其中为对象创建一个 weak_entry_t 条目,将弱引用指针添加到该条目的 referrers 数组中。
2. 弱引用的销毁

当被引用的对象即将被释放时,会调用 objc_destroyWeak 函数,该函数的主要流程如下:

  • 调用 storeWeak 函数,在 SideTable 中查找对应的 weak_table_tweak_entry_t 条目。
  • weak_entry_treferrers 数组中移除该弱引用指针。
  • 如果 weak_entry_t 中的弱引用指针数量变为 0,则从 weak_table_t 中移除该条目。
3. 对象释放时弱引用的置为 nil

当对象的引用计数变为 0 并即将被释放时,会调用 objc_dealloc 函数,该函数会进一步调用 weak_clear_no_lock 函数,该函数的主要流程如下:

  • SideTable 中查找对应的 weak_table_tweak_entry_t 条目。
  • 遍历 weak_entry_treferrers 数组,将所有弱引用指针置为 nil
  • weak_table_t 中移除该 weak_entry_t 条目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/17944.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——红黑树的实现

目录 1 红黑树的概念 1.1 红黑树的规则 1.2 红黑树是如何确保最长路径不超过最短路径的2倍的&#xff1f; 1.3 红黑树的效率 2 红黑树的实现 2.1 红黑树的结构 2.2 红黑树的插入 2.2.1 红黑树插入节点的大概过程 2.2.2 情况1&#xff1a;只变色&#xff0c;不旋转 2.2.3 情况…

Spring Boot中使用Flyway进行数据库迁移

文章目录 概要Spring Boot 集成 FlywayFlyway 其他用法bug错误Flyway版本不兼容数据库存在表了Flyway 的校验和&#xff08;Checksum&#xff09;不匹配 概要 在 Spring Boot 项目开发中&#xff0c;数据库的变更不可避免。手动执行 SQL 脚本不仅容易出错&#xff0c;也难以维…

多态、虚函数、动态绑定、虚指针加虚表是同一件事情。

编译会自动加红色代码 左边拥有右边。由内而外构造、由外到内进行析构。 虚指针跟虚表。当一个类有虚函数的时候&#xff0c;对象里面就会多一个指针。从内存角度思考继承。 静态绑定。现在如果通过指针去调用虚函数&#xff0c;编译器就不会进行静态绑定&#xff0c;而做动态绑…

深入了解Text2SQL开源项目(Chat2DB、SQL Chat 、Wren AI 、Vanna)

深入了解Text2SQL开源项目&#xff08;Chat2DB、SQL Chat 、Wren AI 、Vanna&#xff09; 前言1.Chat2DB2.SQL Chat3.Wren AI4.Vanna 前言 在数据驱动决策的时代&#xff0c;将自然语言查询转化为结构化查询语言&#xff08;SQL&#xff09;的能力变得日益重要。无论是小型创业…

Qwen2-VL 的重大省级,Qwen 发布新旗舰视觉语言模型 Qwen2.5-VL

Qwen2.5-VL 是 Qwen 的新旗舰视觉语言模型&#xff0c;也是上一代 Qwen2-VL 的重大飞跃。 Qwen2.5-VL主要特点 视觉理解事物&#xff1a;Qwen2.5-VL不仅能够熟练识别花、鸟、鱼、昆虫等常见物体&#xff0c;而且还能够分析图像中的文本、图表、图标、图形和布局。 代理性&…

2. grafana插件安装并接入zabbix

一、在线安装 如果不指定安装位置&#xff0c;则默认安装位置为/var/lib/grafana/plugins 插件安装完成之后需要重启grafana 命令在上一篇讲到过 //查看相关帮助 [rootlocalhost ~]# grafana-cli plugins --help //从列举中的插件过滤zabbix插件 [rootlocalhost ~]# grafana…

【Linux】Ubuntu Linux 系统——Node.js 开发环境

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天星期五了&#xff0c;同时也是2025年的情人节&#xff0c;今晚又是一个人的举个爪子&#xff01;&#xff01; &#x1f642; 本文是有关Linux 操作系统中 Node.js 开发环境基础知识&#xff0c;后续我将添加更多相关知识噢&a…

DeepSeek全方位解读:模型介绍,优势及应用场景

DeepSeek全方位解读&#xff1a;领先科技背后的革新力量 前言1.DeepSeek整体介绍2.DeepSeek-R13.DeepSeek-V34.DeepSeek系列模型之间的关系5.Deepseek优势及应用场景6.模型参数与量化精度的关系7.行业部署Deepseek及应用情况 前言 在当今快速发展的科技世界里&#xff0c;人工…

电脑端调用摄像头拍照:从基础到实现

文章目录 1. 了解navigator.mediaDevices.getUserMedia API2. 创建 HTML 结构3. 编写 JavaScript 代码3.1 打开摄像头3.2 拍照 4. 完整代码5. 测试6. 注意事项及部署 在现代 Web 开发中&#xff0c;调用摄像头进行拍照是一个常见的功能&#xff0c;尤其是在需要用户上传头像、进…

windows平台上 oracle简单操作手册

一 环境描述 Oracle 11g单机环境 二 基本操作 2.1 数据库的启动与停止 启动: C:\Users\Administrator>sqlplus / as sysdba SQL*Plus: Release 11.2.0.4.0 Production on 星期五 7月 31 12:19:51 2020 Copyright (c) 1982, 2013, Oracle. All rights reserved. 连接到:…

Java面试——Tomcat

优质博文&#xff1a;IT_BLOG_CN 一、Tomcat 顶层架构 Tomcat中最顶层的容器是Server&#xff0c;代表着整个服务器&#xff0c;从上图中可以看出&#xff0c;一个Server可以包含至少一个Service&#xff0c;用于具体提供服务。Service主要包含两个部分&#xff1a;Connector和…

3. 导入官方dashboard

官方dashboard&#xff1a;https://grafana.com/grafana/dashboards 1. 点击仪表板 - 新建 - 导入 注&#xff1a;有网络的情况想可以使用ID&#xff0c;无网络情况下使用仪表板josn文件 2. 在官方dashboard网页上选择符合你现在数据源的dashboard - 点击进入 3. 下拉网页选…

你如何利用SIMD(如SSE/AVX)优化图像处理的性能?

SIMD优化问题 1. SIMD 在图像处理中的优化方式2. 典型应用场景3. SIMD 的常见优化技巧4. 总结 利用 SIMD&#xff08;Single Instruction, Multiple Data&#xff09; 指令集&#xff08;如 SSE/AVX/AVX2/AVX-512&#xff09;优化图像处理的性能&#xff0c;可以极大地提升计算…

高并发场景下,如何用无锁实现高性能LRU缓存?

《百万人高并发场景下&#xff0c;我如何用无锁实现高性能LRU缓存&#xff1f;》 LRU算法核心原理 LRU&#xff08;Least Recently Used&#xff09;算法是缓存系统的核心淘汰策略&#xff0c;其核心逻辑可以用一张流程图描述&#xff1a; &#xff08;图&#xff1a;访问数…

HAL库框架学习总结

概述&#xff1a;HAL库为各种外设基本都配了三套 API&#xff0c;查询&#xff0c;中断和 DMA。 一、HAL库为外设初始化提供了一套框架&#xff0c;这里以串口为例进行说明&#xff0c;调用函数 HAL_UART_Init初始化串口&#xff0c;此函数就会调用 HAL_UART_MspInit&#xff0…

LAWS是典型的人机环境系统

致命性自主武器系统&#xff08;Lethal Autonomous Weapons Systems&#xff0c;LAWS&#xff09;是一种典型的人机环境系统&#xff0c;它通过高度集成的传感器、算法和武器平台&#xff0c;在复杂的战场环境中自主执行任务。LAWS能够自主感知环境、识别目标、做出决策并实施攻…

【16届蓝桥杯寒假刷题营】第1期DAY4

4.可达岛屿的个数 - 蓝桥云课 题目背景 在一个神奇的魔法世界中&#xff0c;有一座古老的迷幻之城。迷幻之城被分成 n 个鸟屿&#xff0c;编号从 1 到 n&#xff0c;共有 m 座桥。迷幻之城的居民们希望能够建立起紧密的联系&#xff0c;每个岛屿上的居民都想知道自己最多能到…

【物联网】电子电路基础知识

文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…

数据结构 04

4. 栈 4.2. 链式栈 4.2.1. 特性 逻辑结构&#xff1a;线性结构 存储结构&#xff1a;链式存储结构 操作&#xff1a;创建&#xff0c;入栈&#xff0c;出栈&#xff0c;清空&#xff0c;获取 4.2.2. 代码实现 头文件 LinkStack.h #ifndef __LINKSTACK_H__ #define __LINKST…

【云安全】云原生-K8S(四)安全问题分析

Kubernetes&#xff08;K8S&#xff09;因其强大的容器编排能力成为了云计算和微服务架构的首选&#xff0c;但同时也带来了复杂的安全挑战。本文将概述K8S的主要安全问题&#xff0c;帮助安全工程师理解潜在威胁&#xff0c;并采取相应的防护措施。 K8S 攻击面概览 下面两张…