AI 加持的代码编写实战:快速实现 Nginx 配置格式化工具

news2024/11/17 12:40:31

本篇文章聊聊如何使用 GPT 快速完成一个开源小项目,解决实际的问题,顺手点亮 GitHub 上 Nginx 开源社区的贡献者图标。

“Talk is Cheap,Show you the Code。”

写在前面

整理了一篇本该上个月就发出的内容。

前段时间,有个投资人朋友,问了我好几会到底如何使用 GPT 或相关工具来写代码的,希望能有个“step by step”的教程,正巧前几天有这么一个例子,就写一篇文章吧。

其实,我之前已经写过很多篇关于 Nginx 的实践内容了,我很难说我不喜欢这款实践性极强的开源软件。上个月在折腾内部服务的时候,再次用到了 Nginx 这个老伙计,以及我曾经分享过很多次的 NJS。

为了更快的验证功能(偷懒不想写代码),我打开了 GitHub 上 Nginx 官方社区的 nginx/njs-examples 寻找示例配置。

当我在代码编辑器里打开官方项目的配置时,映入眼帘的是方佛是从 90 年代到现在的内容:

  • 最直观的问题是缩进符号混着用,“Tab”和空格“交相辉映”,而且数量“随心所欲”;
  • 其次不同的内容中,哪怕是相同含义的 return 表达,配置中的写法也是“千变万化”;
  • 最难以让我忍受的是,编辑器中的格式化插件会破坏掉正确的配置语法结构,当我翻看插件代码仓库和其核心依赖组件(nginxbeautifier)的时候,我发现了前者已经因为这个问题将项目归档(弃坑),而后者因为缺少社区贡献者对于解决这类问题也进展缓慢,虽然坚持了 7 年的项目十分值得敬佩。

不光是因为有“强迫症”(代码洁癖),更是因为我希望 Nginx 的配置文件都是简洁、美观,以及可靠的,如果没有靠谱好用的 Nginx 格式化工具,那么就做一个呗。

毕竟,Talk is Cheap。

开源的 Nginx 配置格式化工具,Nginx Formatter

完整项目,我已经上传到了 soulteary/nginx-formatter,希望它能帮到你。

当然,也十分欢迎一键三连

方案设计

动手之前,我们最好先做一个简单的规划,以及针对这个规划做一些适当的可行性调研。

社区已有项目调研

我简单翻阅了社区中有关于 Nginx 配置格式化相关的项目,包括其中一个已经坚持了 7 年的格式化开源软件 nginxbeautifier 的代码和历史演进过程。

我发现在 GitHub 社区中,Nginx 代码格式化相关的工具不多,但却分为了三种语言阵营,两种玩法。按照语言来分类:

  • Python 实现 (nginxfmt.py 项目)
  • JavaScript 实现 (借鉴自 nginxfmt.py
  • Golang 实现(借鉴自 nginxfmt.py

按照处理方式来看,则是下面两类玩法:

  • 基于字符串特征进行格式化处理
  • 基于 AST 语法树进行格式化处理

第一种方法,相对比较“治标”,解决问题会更快一些,但可能会因为 Nginx 配置的演进越来越复杂,解析、格式化能力跟不上迭代,以及判断逻辑不够周全,导致格式化出错。

比如,raynigon/vscode-nginx-formatter 这个在 VSCode 插件市场里被下载了二十万次的插件,就是采用这种方案(基于 JS 版本的 nginxbeautifier),以至于有用户确实反馈,会“损坏”配置。

第二种方法,相对比较“治本”,解决问题更靠谱,但是需要完整的了解 Nginx 配置文件的定义,实现起来需要额外的一些时间。

况且,我也不太相信创建项目有一段时间的语法解析方案,对于现在的 Nginx 配置的支持能力,目前的 Nginx 配置丰富程度早已经不是早些年可比的了。

所以,这里我们先来实现一个能解决问题,但是不那么完美的方案吧。

使用 AutoGPT 做方案交叉验证

当然,在实现之前,我们可以使用 AutoGPT 等方法,来对我们想要做的事情,或者想法进行任务拆解或分析,来为我们“查缺补漏”。

使用 AutoGPT 做方案的交叉验证

类似的工具很多,社区里随便找一个用 Docker 跑起来就好。因为模型的结果有一定的随机性,所以我们可以反复尝试,以及适当调整 “Prompt”,让模型的回答更全面一些。 因为很多项目里使用的“提示咒语”默认都是英文,所以在执行之后,得到的结果也都是英文的结果。

这里我们可以使用 ChatGPT 来进行偷懒,只需要把内容复制粘贴到 ChatGPT 里,然后在上面添加一句要求:“将下面的内容翻译为中文”。

使用 ChatGPT 进行内容翻译

然后,我们稍等片刻,这些内容就变成了阅读更简单的母语内容啦。

使用 ChatGPT 翻译完毕的内容

最终方案设计

结合上文提到的各种内容,结合实现时间成本,我们考虑使用“基于字符串特征进行格式化处理”的方案来解决问题。

我期望工具能够开箱即用,没有任何依赖问题,所以我的基础技术栈选择的是 Golang。

然而,Golang 生态下,并没有类似 Python 或者 JavaScript 生态的格式化工具库,所以我们需要手动实现一个格式化工具库,或者让社区的 Python 或者 JavaScript 代码能够在我们的 Golang 程序中运行,内化为我们程序的一部分。

相比较前者,后者的代码实现更少一些,实现速度更快一些,所以我们就用这个方式来玩吧。

实战:询问 GPT 如何实现基础功能

在前文中,我们提到了开源社区现在的各种实现,以及我们计划使用的方案。在实际 Coding 的时候,我们可以借助 ChatGPT 来完成逻辑。

为了演示最低成本的实现,这里我们虽然能够使用 GPT-4,但是考虑到多数人还是有使用限制,我们用 GPT 3.5 来实现我们所需要的东西。

调整 JavaScript 版的格式化程序实现

虽然 JavaScript 版的格式化程序有用户吐槽,但其实,只要我们修正其中的“corner cases”,程序还是能够使用的。完整代码在项目中的 soulteary/nginx-formatter/internal/formatter/beautifier.js,两百行出头。整体结构如下:

/**
 * - Soulteary Modify the JavaScript version for golang execution, under [Apache-2.0 license], 18/04/2023:
 *   - simplify the program, fix bugs, improve running speed, and allow running in golang
 *   - https://github.com/soulteary/nginx-formatter
 *
 * History:
 * - Yosef Ported the JavaScript beautifier under [Apache-2.0 license], 24/08/2016
 *   - https://github.com/vasilevich/nginxbeautifier
 * - Slomkowski Created a beautifier for nginx config files with Python under [Apache-2.0 license], 24/06/2016
 *   - https://github.com/1connect/nginx-config-formatter (https://github.com/slomkowski/nginx-config-formatter)
 */

/**
 * Grabs text in between two seperators seperator1 thetextIwant seperator2
 * @param {string} input String to seperate
 * @param {string} seperator1 The first seperator to use
 * @param {string} seperator2 The second seperator to use
 * @return {string}
 */
function extractTextBySeperator(input, seperator1, seperator2) {
...
}

/**
 * Grabs text in between two seperators seperator1 thetextIwant seperator2
 * @param {string} input String to seperate
 * @param {string} seperator1 The first seperator to use
 * @param {string} seperator2 The second seperator to use
 * @return {object}
 */
function extractAllPossibleText(input, seperator1, seperator2) {
...
}

/**
 * @param {string} single_line the whole nginx config
 * @return {string} stripped out string without multi spaces
 */
function strip_line(single_line) {
...
}


/**
 * @param {string} configContents the whole nginx config
 */
function clean_lines(configContents) {
...
}


function join_opening_bracket(lines) {
...
}

function fold_empty_brackets(lines) {
...
}


function add_empty_line_after_nginx_directives(lines) {
...
}


function fixDollarVar(lines) {
...
}


var options = { INDENTATION: "\t" };

function perform_indentation(lines) {
...
}


function FormatNginxConf(text, indentSize = 2, indentChar = " ") {
...
}

在实现的过程中,你有任何懒得动手的地方,都可以交给 ChatGPT,比如张贴之前的老代码,询问它这段代码的含义:

使用 ChatGPT 解读代码

尤其是对于陈旧的老代码(特别是别人写的),我们可以通过 ChatGPT 来进行含义解读,并且要求它来一些代码的单元测试。这样可以极大的缩短我们在阅读代码上花费的时间。

使用 ChatGPT 解读后的代码

当然,很多时候,它生成的内容是有问题的,需要我们进行仔细甄别或进行额外的测试验证。但即使如此,也会比我们从零到一自己搞来的快。

让 JavaScript 能够在 Golang 中运行

前文提到,因为 Golang 中没有类似 ngxfmt 或者 nginxbeautifier 类似的工具库,所以最快完成我们需求的方式,除了切换技术栈之外,就是将这些不同语言的程序,在 Golang 中直接运行。

这里我们询问下 ChatGPT:“如何在 Golang 中运行 JavaScript 代码”。

询问 ChatGPT 如何在 Golang 中运行 JavaScript 代码

能够看到,在 ChatGPT 的回答中,推荐我们使用 goja,并给出了最简单的实现。这个项目确实是一个有趣的项目,使用纯 Go 实现的 ECMA 5.1 解析引擎,能让我们在 Golang 中直接运行 JavaScript 代码。

当然,除了 goja 之外,参考我之前一个的开源项目soulteary/rss-can,我们也可以使用更强悍的 v8go 来实现这个功能,实际执行速度更快一些,但会让构建文件的体积稍大一些。

让程序能够一个文件解决战斗

前文提到,我们希望程序能够“一个文件走天下”,不需要带着一堆依赖、配置文件等乱七八糟的东西。

我们都知道 Golang 能够编译成一个文件,但是一般情况下只能处理 Go 文件的编译构建。那么如何将 JavaScript 变成 Golang 的一部分呢?如果是你我的老读者,你一定会想起我曾经提到的 go embed 嵌入方案。

如果你没有了解过这个技术方案,我推荐你看一下 Golang 资源嵌入方案,了解它的来龙去脉、几种方案的性能几何。

不过,这里我们想实现具体功能,并且越快越好,我们不妨直接问问 ChatGPT:“如何在 Golang 里使用 Embed ,嵌入一个 JS 文件。”

如何使用 Go Embed 将 JS 和 Golang 合二为一

使用追问,完成我们要的代码

比如,在上面的章节中,我们询问如何在 Golang 中运行 JavaScript 代码。

结合实际需要,我们应该需要构建一个 Go 的格式化函数,接受一些必要的参数,比如:原始配置内容、缩进数量、缩进符。

那么我们可以在具体的会话中,追加问题:

如何使用 Go Embed 将 JS 和 Golang 合二为一

一般情况下,ChatGPT 的表现是可以的:

ChatGPT 针对追问的回答

类似上面提到的具体代码实现,我们在写工具的过程中会有许多许多。

但是并非每次生成的代码,都能够派上用场,以及并非每次的代码都是正确的,这时,我们可以基于已经生成好的代码,进行多轮对话,让 ChatGPT 的答案,能够接近我们的需求,如果答的不对,我们可以让他重新生成。如果多次重新生成依旧不能让你满意,那么大概率是问题提的不够贴近,我们需要适当调整问题。

优化程序生成的代码

就上面的代码而言,虽然能够满足需求,但是写的未免太过于啰嗦。而默认生成的代码一般都是直白的逻辑呈现,并且因为我们的提问都比较简单,所以都有一些啰嗦。

所以,我们需要针对 GPT 生成的内容做一些优化,比如上面提到的比较关键的 Formatter 函数(位于项目位置 soulteary/nginx-formatter/internal/formatter/formatter.go):

package formatter

import (
	"fmt"

	"github.com/dop251/goja"
)

func Formatter(s string, indent int, char string) (string, error) {
	if s == "" {
		return "", nil
	}
	vm := goja.New()
	v, err := vm.RunString(fmt.Sprintf("%s;FormatNginxConf(`%s`, %d, `%s`)", JS_FORMATTER, s, indent, char))
	if err != nil {
		return "", err
	}
	return v.String(), nil
}

当然,在过程中你也可以咨询 ChatGPT ,具体的细节优化,函数使用。

实战:完善程序阶段

当我们把程序的核心功能实现完毕之后,剩下的就都是比较通用的边边角角的功能或者“质量保证”相关的测试啦。

编写一般功能,都比较简单,使用下面的句式即可完成任务:

  • 使用 Golang 完成 xxx 功能
  • 使用 Golang 语言中的 xx 框架/工具包,来完成 xxx 功能

这里就不多做展开,浪费篇幅了,我们聊聊比较典型的单元测试。

使用 GPT 完成单元测试

应该不会有太多工程师对于写测试感兴趣,尤其是程序频繁变动的前提下,我们写的测试越多,可能随着项目变化变成废代码的可能性也就越高。

但是,如果不需要我们动手,这个事情就能完成呢?

直接问 ChatGPT 要单元测试代码

比如,我们将上面的代码直接粘贴到 ChatGPT 中,要求他完成单元测试。

ChatGPT 完成的单元测试

如果是上下文不够明确、缺少 Heredoc 注释的函数,一般会生成比较泛的代码,如果你愿意完善注释或者多提供一些上下文,那么你将得到覆盖率 80~90%,甚至完全覆盖的测试代码。

实战:编写效率提升

除了和 ChatGPT 聊天,笨笨的复制粘贴代码之外,是否还有更偷懒的方式写代码呢?

答案是有的,借助离线和在线的语言模型即可。

本地代码补全模型的使用

关于离线模型做代码补全,是一个老话题了,如果你追求更快的实时性,以及和代码工具的贴合程度。就个人体验来说,我暂时还推荐 TabNine。

至于其他的工具,建议感兴趣的同学自己试试看,包括性能、生成结果、代码 IDE 的兼容性等等,感觉差距还是挺明显的。

我使用了三年左右,本地模型尺寸拢共 1.2G,如果一周写代码的时间比较多,至少能够帮助我节约 13~30% 的输出时间。

# pwd
/Users/soulteary/Library/Application Support/TabNine/models

# ls
29b87067.tabninemodel b8373e4b.tabninemodel ce94127b.tabninemodel
# du -hs *
241M	29b87067.tabninemodel
685M	b8373e4b.tabninemodel
256M	ce94127b.tabninemodel

# du -hs .
1.2G	.

不过,TabNine 的上限取决于你让它见过的代码有多少,以及有多好,培养好的模型,和喂电子宠物差不多,需要时间。

在线代码补全模型的使用

如果你想开箱即用,并且代码没有那么敏感,那么在线代码补全,会更适合你。

Copilot,好用的代码补全工具

这里唯一推荐的是:github/copilot,如果你的网络通畅,一般情况下你的代码补全都能够在 1s~2s 内完成。

默认情况下,你可能需要花一些小钱,来订阅这个功能。很幸运,我的账号有资格直接使用它。

免费不限量的 Copilot

网上应该有很多对于 Copilot 的介绍了,我这里介绍两个实际使用时的小技巧。

基于上下文(打开的文件)生成

在实际的程序编写中,我们会打开很多不同的文件,但是如果我们要生成的代码只和某个或者某几个文件相关,可以考虑关闭其他的文件。

基于上下文(包括剪贴板)生成

如果我们想针对某段具体的内容进行代码生成,在生成之前,可以顺手复制粘贴一下我们想作为上下文进行代码生成的内容。在生成代码的时候,能省一些事情。

实战:收尾工作

编码工作完成之后,我们还需要做一些内容的收尾。

比如,编写中英双语的项目文档,以及设计项目的 Logo。

使用 GPT 完成开源项目的文档

这里和前文中使用 AutoGPT 一样,我们可以多次提交内容,让 ChatGPT 帮助我们写出项目的框架。

让 ChatGPT 生成项目文档模版

然后我们根据实际情况,把文档中的内容进行替换即可。

至于英文文档,只需要和上文中将 “Auto GPT 内容翻译中文”一样,反过来,让 ChatGPT 将内容翻译成英文即可。

是不是简单省事。

使用 MidJourney 完成项目图标

编写项目最难的部分之一,就是为项目设计一个 Logo。不过现在有了 SD、Midjoruney ,这件事变的太简单了。

我们只需要对它下命令:“帮助我设计一个 Logo,Logo 的内容是…”

使用 Midjoruney 生成项目 Logo

当然,在实际的使用中,如果我们将 prompt 改写为英文,对于模型而言,生成的效果会更好一些。

提前将 Prompt 内容翻译为英文

如果你经常使用 Midjoruney 等图文模型,可以试试使用之前在 GitHub 热榜上待了很久的,我另外一个开源项目:《八十行代码实现开源的 Midjourney、Stable Diffusion “咒语”作图工具》。

其他

好了,文章的基本内容,到这里就聊完了。

我们来聊聊开源社区里的趣事。

开源社区里的趣事

其实去年的时候,在 Nginx 社区里,有一个老外曾留下一个 issue,包含了几个去掉配置中多余空格的修改。

社区里的 PR

我当时看到了这个提交,觉得因为没有提供一致性的标准或可复现的工具,这个属于水 PR。于是,留了一条评论 “这个变更似乎没有必要,或许提供一个通用的格式化工具,对于开发者而言更有价值。”

但是,不论是这个变更提交者,还是项目相关维护者都没有继续进行回复。于是,这个 issue 就挂了一年之久。正巧借着这个机会,就用 ChatGPT 来解决这个事情吧。

彻底解决 Nginx 社区项目的提交

目前,我已经用这个小工具完成了 Nginx 官方配置仓库中的“内容翻修”,以及点亮了 Nginx 开源社区的贡献者图标记录。

点亮了的 Nginx 项目贡献者图标

最后

终于将这篇待在草稿箱里一个月的文章整理了出来,希望接下来,随着业务的正常发展,我能够有更多的时间来分享如何“为了不折腾而折腾”的事情。

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾的小伙伴。

在不发广告的情况下,我们在里面会一起聊聊软硬件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术资料。

喜欢折腾的小伙伴,欢迎阅读下面的内容,扫码添加好友。

关于“交友”的一些建议和看法

添加好友时,请备注实名和公司或学校、注明来源和目的,否则不会通过审核。

关于折腾群入群的那些事


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2023年05月20日
统计字数: 10491字
阅读时间: 21分钟阅读
本文链接: https://soulteary.com/2023/05/20/code-writing-practice-supported-by-ai-quickly-implement-nginx-configuration-formatting-tool.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈JDK8的垃圾回收器

JDK1.8默认使用Parallel Scavenge作为年轻代的垃圾回收器,使用Parallel Old作为老年代的垃圾回收器,又称为PS MarkSweep。 Parallel Scavenge 收集器 Parallel Scavenge收集器又称为吞吐量优先收集器,和ParNew收集器类似,是一个新生代收集器。…

【OpenCV DNN】Flask 视频监控目标检测教程 01

欢迎关注『OpenCV DNN Youcans』系列,持续更新中 【OpenCV DNN】Flask 视频监控目标检测教程 01 【OpenCV DNN】Flask 视频监控目标检测教程 01 1. 面向Python程序的Web框架2. Flask 框架的安装与使用2.1 Flask 安装2.2 Flask 框架例程2.3 绑定IP和端口2.4 Flask路…

2023-5-20基于52单片机的智能家居系统(蓝牙)

资料已上传在微信公众号:风吹摇铃 奔赴星海 此系统可根据开发板原理图搭配外载模块实现功能,也可以根据原理图焊接或者PCB焊接。 注意:根据开发板搭载外部模块实现功能,需根据开发板原理图修改代码 0、整理及编写了19个常用的5…

NameServer路由注册与发现

NameServer在RocketMQ中主要承担的就是路由的管理、服务注册、以及服务的发现。在RocketMQ这承担着很重要的责任。 整体架构: 消息生产者在发送消息前需要考虑的问题就是,我需要发给谁?地址在哪儿?对于消费者也一样。那么NameSer…

软件工程 | 期末复习

一、软件与软件危机 1、软件发展经历三个阶段:程序设计、程序系统、软件工程 2、软件的概念:软件是计算机系统与硬件相互依存的另一部分,包括程序、数据以及相关文档的完整集合,软件程序数据文档 数据:使程序能够适…

测试人员转型是大势所趋:我的十年经验告诉我,你必须要行动起来了。

做测试十多年,有不少人问过我下面问题: 现在的手工测试真的不行了吗? 测试工程师,三年多快四年的经验,入门自动化测试需要多久? 自学自动化测试到底需要学哪些东西? 不得不说,随着行…

学习open62541 --- [76] 使用智能指针处理内存释放问题

在使用监测项时,一般都会加一个context,然后在回调函数里使用这个context,这就需要保证context的内存空间在执行回调函数时是有效的。往往有以下三种方法: 使用静态内存空间:使用static创建静态变量,然后把…

【Python 爬虫常见的报错及其解决方法】零基础也能轻松掌握的学习路线与参考资料

Python 爬虫被广泛应用于数据采集和分析。然而,爬虫在运行过程中常常会遇到各种问题和错误,降低了爬虫效率、准确性和可靠性。因此掌握爬虫常见报错及其解决方法是非常关键的。本文将介绍 Python 爬虫常见的报错及其解决方法,并提供参考资料和…

内存泄漏的原因,内存泄漏如何避免?内存泄漏如何定位?

1. 内存溢出 内存溢出 OOM (out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。 2. 内存泄…

PyTorch LSTM和LSTMP的原理及其手写复现

PyTorch LSTM和LSTMP的原理及其手写复现 0、前言全部参数的细致介绍代码实现Reference 0、前言 关于LSTM的原理以及公式其实在这篇博客一步一步详解LSTM网络【从RNN到LSTM到GRU等,直至attention】讲的非常清晰明了了。 这里就是写出LSTM的pytorch的实现,…

【随笔记】全志 T507 PF4 引脚无法被正常设置为中断模式的问题分析

相关信息 硬件平台:全志T507 系统版本:Android 10 / Linux 4.9.170 问题描述:PF4 无法通过标准接口设置为中断模式,PF1、PF2、PF3、PF5 都可以。 分析过程 一开始以为是引脚被其它驱动占用引起,或者该引脚不具备中断…

高光谱成像技术在果蔬品质检测中的应用

在当前市场经济背景下,食品安全问题是消费者最为关心的问题之一,尤其是果蔬产品,农药残留问题和品质问题直接关系着消费者的权益和人身安全。针对传统化学检测的缺陷,本文结合高光谱成像技术,对其在果蔬品质与安全无损…

【C++】多态的概念/重写/虚表/抽象类

多态 多态的概念多态的定义和实现重写抽象类多态的原理虚表的构建原理虚函数的调用原理 多态的概念 多态就是多种形态,传递不同的对象,会调用不同的方法。 多态的定义和实现 那么在C语法中,多态是如何实现的呢? 我们首先要在继承…

vue学习 - 基础篇

初始工程结构 这里我们使用script标签从cdn获取vue.js, 而不是使用脚手架vue-cli, 因为cdn比较方便一点, 也不用配置node之类的比较麻烦 index.html <!DOCTYPE html> <html><head><title>VueJS Course</title><link rel"stylesheet"…

第三篇、基于Arduino uno,用oled0.96寸屏幕显示dht11温湿度传感器的温度和湿度信息——结果导向

0、结果 说明&#xff1a;先来看看拍摄的显示结果&#xff0c;如果是你想要的&#xff0c;可以接着往下看。 1、外观 说明&#xff1a;本次使用的oled是0.96寸的&#xff0c;别的规格的屏幕不一定适用本教程&#xff0c;一般而言有显示白色、蓝色和蓝黄一起显示的&#xff0…

RabbitMQ日常使用小结

一、使用场景 削峰、解耦、异步。 基于AMQP(高级消息队列协议)协议来统一数据交互,通过channel(网络信道)传递信息。erlang语言开发&#xff0c;并发量12000&#xff0c;支持持久化&#xff0c;稳定性好&#xff0c;集群不支持动态扩展。 RabbitMQ的基本概念 二、组成及工作流…

可见性原子性有序性的+线程传参的方式+Java如何实现多个线程之间共享数据+线程间通信+死锁产生

//为了均衡CPU和内存的速度差异,增加了缓存 导致了可见性的问题; //操作系统增加了进程 线程 分时复用CPU,均衡CPU和io设备的速速差异 导致了原子性问题; //jvm指令重排序(优化指令排序) 导致了有序性的问题 可见性问题是指 线程A修改共享变量,修改后CPU缓存中的数据没有及时同…

Emacs之目前最快补全插件lsp-bridge(八十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

数据分析12——Pandas中数据合并方法

0、前言&#xff1a; 在pandas中进行数据合并的操作和数据库中的join操作非常类似。 1、merge横向合并&#xff1a; 前言&#xff1a;该函数只能做横向合并函数名&#xff1a;merge()函数参数&#xff1a; left: 数据类型为’DataFrame | Series’&#xff0c;需要进行合并的…

[CTF/网络安全] 攻防世界 PHP2 解题详析

[CTF/网络安全] 攻防世界 PHP2 解题详析 index.php.phps扩展名姿势 翻译&#xff1a;你能给这个网站进行身份验证吗&#xff1f; index.php index.php是一个常见的文件名&#xff0c;通常用于Web服务器中的网站根目录下。它是默认的主页文件名&#xff0c;在访问一个网站时&am…