前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Go 1.24: runtime.AddCleanup, 改进 runtime.SetFinalizer 的一些问题

Go 1.24: runtime.AddCleanup, 改进 runtime.SetFinalizer 的一些问题

作者头像
萝卜要努力
发布于 2025-03-07 08:02:22
发布于 2025-03-07 08:02:22
12500
代码可运行
举报
文章被收录于专栏:萝卜要加油萝卜要加油
运行总次数:0
代码可运行

以前,我写过一篇文章介绍runtime.SetFinalizer 这个函数,用于在对象被清理的时候调用,但是这个函数有一些问题,导致它的使用频率比较低。

  1. 在 Go 中使用 SetFinalizer 方法时,必须确保传递给它的对象引用指向分配内存的起始位置(即分配内存块的第一个字节)。这要求程序员理解“分配”(allocation)的概念,而这个概念通常在 Go 语言的抽象层级中并未明确暴露。
  2. 对象只能定义一个SetFinalizer
  3. 带有SetFinalizer的对象如果涉及到任何引用循环,将无法被释放,SetFinalizer也不会运行。
  4. 带有SetFinalizer的对象至少需要两个 GC 循环才能被释放。 https://github.com/golang/go/issues/67535

对于第一条,我们可以用一个例子说明

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
"fmt"
"runtime"
)

type MyStruct struct {
    Field int
}

funcmain() {
    obj := &MyStruct{Field: 42}
    runtime.SetFinalizer(obj, func(m *MyStruct) {
        fmt.Println("Finalizer called for:", m)
    })

// 错误示例:传递字段引用而非对象本身
// runtime.SetFinalizer(&obj.Field, func(m *int) {
// fmt.Println("Finalizer called for:", *m)
// })
}

基于上面的原因,在Golang 1.24 中添加了一个新的函数runtime.AddCleanUp 来替换runtime.SetFinalizer

注意:runtime.AddCleanupruntime.SetFinalizer 都不保证 清理函数一定会被执行。

AddCleanup的设计目标是解决runtime.SetFinalizer的诸多问题,特别是避免对象复活,从而允许对象的及时清理,并支持对象的循环清理。 AddCleanup函数的原型如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
funcAddCleanup[T,Sany](ptr *T, cleanupfunc(S), arg S) Cleanup

基于此,可以写一个RAII(Resource Acquisition Is Initialization)的 Demo 。在go weak 的文章中,我们实现了一个固定长度的cache,改一下代码,添加一个newElemWeak 方法,当最旧的elem 被逐出的时候,会自动调用deletekeycache 中删除。不需要我们手动管理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func(c *WeakCache) newElemWeak(elem *list.Element) weak.Pointer[list.Element] {
    elemWeak := weak.Make(elem)
    runtime.AddCleanup(elem, func(namestring) {
        delete(c.cache, name)
    }, elem.Value.(*CacheItem).key)
    return elemWeak
}

需要注意的几个问题

AddCleanupptr的约束很少,支持为同一个指针附加多个清理函数。不过,如果ptr可以从cleanuparg中可达,ptr将永远不会被回收(memory leak),清理函数也永远不会运行,目前来看这种情况也不会panic。 或许以后会用GODEBUG=gccheckmark=1 这种模式来检测? 比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
funcNewFileResource(filenamestring) (*os.File, error) {
    file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
returnnil, err
    }

    runtime.AddCleanup(file, func(f *os.File) {
        fmt.Println("close f")
        _ = f.Close()
    }, file)

return file, nil
}

fmt.Println("close f") 不会被打印,file 也不会被关闭。

Try It 当给一个ptr绑定多个cleanup 的时候,因为cleanup 是在一个独立的goroutine 中运行,所以它的运行顺序可能是不固定的。

特别是,如果几个对象相互指向并且同时变成 unreachable,它们的清理函数都可以运行,并且可以以任何顺序运行。即使对象形成一个循环也是如此(runtime.SetFinalizer 在这种情况下会产生内存泄露)。 例如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
funcmain() {
    x := MyStruct{Name: "X"}
    y := MyStruct{Name: "Y"}

    x.Other = &y
    y.Other = &x
//runtime.SetFinalizer(&x, func(x *MyStruct) {
// fmt.Printf("Finalizer for %s is called\n", x.Name)
//})
//runtime.SetFinalizer(&y, func(y *MyStruct) {
// fmt.Printf("Finalizer for %s is called\n", y.Name)
//})
    xName := x.Name
    runtime.AddCleanup(&x, func(namestring) {
        fmt.Println("Cleanup for", x)
    }, xName)
    yName := y.Name
    runtime.AddCleanup(&y, func(namestring) {
        fmt.Println("Cleanup for", x)
    }, yName)
    time.Sleep(time.Millisecond)
    runtime.GC()
    time.Sleep(time.Millisecond)
    runtime.GC()
}

运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
➜  AddCleanUp git:(main) ✗ gotip run main.go
Cleanup for Y
Cleanup for X

SetFinalizer 的会阻止 GC,但是AddCleanup 能够正常执行

参考资料

  1. https://github.com/golang/go/issues/67535
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萝卜要加油 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
R语言风险价值:ARIMA,GARCH,Delta-normal法滚动估计VaR(Value at Risk)和回测分析股票数据|附代码数据
此分析的目的是构建一个过程,以在给定时变波动性的情况下正确估计风险价值。风险价值被广泛用于衡量金融机构的市场风险。我们的时间序列数据包括 1258 天的股票收益
拓端
2023/07/07
3910
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化
普通的模型对于两个序列的波动分析一般是静态的,但是dcc-garch模型可以实现他们之间动态相关的波动分析,即序列间波动并非为一个常数,而是一个随着时间的变化而变化的系数。其主要用于研究市场间波动率的关系(点击文末“阅读原文”获取完整代码数据)。
拓端
2023/08/30
2140
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化
R语言多元(多变量)GARCH :GO-GARCH、BEKK、DCC-GARCH和CCC-GARCH模型和可视化|附代码数据
从Engle在1982发表自回归条件异方差(ARCH)模型的论文以来,金融时间序列数据的波动性就倍受关注。同时,近几年又出现了研究股票市场的波动传递性
拓端
2023/01/12
1.5K0
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化
普通的模型对于两个序列的波动分析一般是静态的,但是dcc-garch模型可以实现他们之间动态相关的波动分析,即序列间波动并非为一个常数,而是一个随着时间的变化而变化的系数。其主要用于研究市场间波动率的关系。
拓端
2023/02/16
2830
R语言预测期货波动率的实现:ARCH与HAR-RV与GARCH,ARFIMA模型比较|附代码数据
在本文中,波动率是众多定价和风险模型中的关键参数,例如BS定价方法或风险价值的计算。在这个模型中,或者说在教科书中,这些模型中的波动率通常被认为是一个常数
拓端
2023/02/14
7110
R语言股票市场指数:ARMA-GARCH模型和对数收益率数据探索性分析|附代码数据
最近我们被客户要求撰写关于ARMA-GARCH的研究报告,包括一些图形和统计输出。
拓端
2023/02/21
1.1K0
Python使用GARCH,EGARCH,GJR-GARCH模型和蒙特卡洛模拟进行股价预测|附代码数据
在本文中,预测股价已经受到了投资者,政府,企业和学者广泛的关注。然而,数据的非线性和非平稳性使得开发预测模型成为一项复杂而具有挑战性的任务
拓端
2022/12/02
9900
R语言实现:基于GARCH模型的股市危机预警
作者:huozi07 http://blog.csdn.net/huoz07/artile/details/48176587 为防范股票市场上的不确定性和风险,有效地度量股票指数收益率的波动性显得尤为重要。本文运用GARCH族模型拟合了股票指数收益率的波动性方程并实证研究了全球有代表性的上证综指、NASDAQ指数、德国DAX、日本日经指数。结果表明四个国家股票收益率均有聚集性、持续性,股票市场存在着冲击的非对称性。具体而言,美国、德国、日本股票市场对利空消息敏感,而对利好消息保持谨慎。而中国对利好利空消息均
机器学习AI算法工程
2018/03/14
5.3K0
R语言实现:基于GARCH模型的股市危机预警
R语言中的时间序列分析模型:ARIMA-ARCH / GARCH模型分析股票价格|附代码数据
时间序列分析是统计学中的一个主要分支,主要侧重于分析数据集以研究数据的特征并提取有意义的统计信息来预测序列的未来值
拓端
2022/12/21
1.4K0
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化|附代码数据
普通的模型对于两个序列的波动分析一般是静态的,但是dcc-garch模型可以实现他们之间动态相关的波动分析,即序列间波动并非为一个常数,而是一个随着时间的变化而变化的系数。其主要用于研究市场间波动率的关系
拓端
2023/05/10
3610
R语言用GARCH模型波动率建模和预测、回测风险价值 (VaR)分析股市收益率时间序列|附代码数据
风险价值 (VaR) 是金融风险管理中使用最广泛的市场风险度量,也被投资组合经理等从业者用来解释未来市场风险
拓端
2023/02/23
1.3K0
R语言GARCH族模型:正态分布、t、GED分布EGARCH、TGARCH的VaR分析股票指数
VaR方法作为当前业内比较流行的测量金融风险的方法,具有简洁,明了的特点,而且相对于方差来讲,更多的将投资人的损失作为风险具有更好的合理性。
拓端
2022/12/23
7410
R语言分位数回归、最小二乘回归OLS北京市GDP影响因素可视化分析
对于影响北京市GDP 因素分析常用的方法是最小二乘回归。【1】但最小二乘有自身的缺陷,该方法要求较高,例如许多观测数据很难满足全部假设条件(点击文末“阅读原文”获取完整代码数据)。
拓端
2023/08/31
3100
R语言分位数回归、最小二乘回归OLS北京市GDP影响因素可视化分析
R语言MCMC-GARCH、风险价值VaR模型股价波动分析上证指数时间序列
随着金融市场全球化的发展,金融产品逐渐受到越来越多的关注,而金融产品的风险度量成为投资者最关心的问题。金融风险是指由于经济活动的不确定性、市场环境的变化、决策的失误等因素的影响,导致实际回报与预期回报出现偏离的可能性。
拓端
2023/03/03
3200
R语言使用多元AR-GARCH模型衡量市场风险|附代码数据
董事会感到关切的是,公司已连续第五个季度未能实现盈利预期。股东不高兴。罪魁祸首似乎是商品销售成本的波动。
拓端
2022/11/08
3820
Python使用GARCH,EGARCH,GJR-GARCH模型和蒙特卡洛模拟进行股价预测|附代码数据
在本文中,预测股价已经受到了投资者,政府,企业和学者广泛的关注。然而,数据的非线性和非平稳性使得开发预测模型成为一项复杂而具有挑战性的任务
拓端
2023/04/22
6530
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用|附代码数据
这篇文章讨论了自回归综合移动平均模型 (ARIMA) 和自回归条件异方差模型 (GARCH) 及其在股票市场预测中的应用 ( 点击文末“阅读原文”获取完整代码数据******** )。
拓端
2023/06/02
5550
【视频】Copula算法原理和R语言股市收益率相依性可视化分析|附代码数据
copula是将多变量分布函数与其边缘分布函数耦合的函数,通常称为边缘。在本视频中,我们通过可视化的方式直观地介绍了Copula函数,并通过R软件应用于金融时间序列数据来理解它 。
拓端
2023/01/10
9150
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用|附代码数据
这篇文章讨论了自回归综合移动平均模型 (ARIMA) 和自回归条件异方差模型 (GARCH) 及其在股票市场预测中的应用
拓端
2023/01/13
1.8K0
R语言用logistic逻辑回归和AFRIMA、ARIMA时间序列模型预测世界人口|附代码数据
本文应用R软件技术,分别利用logistic模型、ARFMA模型、ARIMA模型、时间序列模型对从2016到2100年的世界人口进行预测
拓端
2023/02/23
8480
推荐阅读
R语言风险价值:ARIMA,GARCH,Delta-normal法滚动估计VaR(Value at Risk)和回测分析股票数据|附代码数据
3910
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化
2140
R语言多元(多变量)GARCH :GO-GARCH、BEKK、DCC-GARCH和CCC-GARCH模型和可视化|附代码数据
1.5K0
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化
2830
R语言预测期货波动率的实现:ARCH与HAR-RV与GARCH,ARFIMA模型比较|附代码数据
7110
R语言股票市场指数:ARMA-GARCH模型和对数收益率数据探索性分析|附代码数据
1.1K0
Python使用GARCH,EGARCH,GJR-GARCH模型和蒙特卡洛模拟进行股价预测|附代码数据
9900
R语言实现:基于GARCH模型的股市危机预警
5.3K0
R语言中的时间序列分析模型:ARIMA-ARCH / GARCH模型分析股票价格|附代码数据
1.4K0
R语言DCC-GARCH模型对上证指数、印花税收入时间序列数据联动性预测可视化|附代码数据
3610
R语言用GARCH模型波动率建模和预测、回测风险价值 (VaR)分析股市收益率时间序列|附代码数据
1.3K0
R语言GARCH族模型:正态分布、t、GED分布EGARCH、TGARCH的VaR分析股票指数
7410
R语言分位数回归、最小二乘回归OLS北京市GDP影响因素可视化分析
3100
R语言MCMC-GARCH、风险价值VaR模型股价波动分析上证指数时间序列
3200
R语言使用多元AR-GARCH模型衡量市场风险|附代码数据
3820
Python使用GARCH,EGARCH,GJR-GARCH模型和蒙特卡洛模拟进行股价预测|附代码数据
6530
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用|附代码数据
5550
【视频】Copula算法原理和R语言股市收益率相依性可视化分析|附代码数据
9150
Python金融时间序列模型ARIMA 和GARCH 在股票市场预测应用|附代码数据
1.8K0
R语言用logistic逻辑回归和AFRIMA、ARIMA时间序列模型预测世界人口|附代码数据
8480
相关推荐
R语言风险价值:ARIMA,GARCH,Delta-normal法滚动估计VaR(Value at Risk)和回测分析股票数据|附代码数据
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档