go中runtime包里面的mutex是什么?runtime.mutex解析
其实在看go源码的时候,发现除了sync包里有个mutex以外,runtime包里也有一个mutex,这个mutex在runtime很多地方都在用。
这个runtime包里面的mutex的结构如下:
目录: /runtime/runtime2.go
代码:
type mutex struct {lockRankStructkey uintptr
}
可以看到他有两个成员,一个是lockRankStruct,一个是key。
先看下lockRankStruct:
lockRankStruct 这个结构体是个空的结构体,在网上有大佬这样描述:
lockRankStruct提供了一种运行时的静态锁排名的机制。静态锁排名会建立文件化的锁之间的总排序顺序,如果违反总的排序,则会报错。只要锁排序是按照文档设计的顺序,锁排序死锁就不会发生。如果要做Go运行时使用这个机制,你需要设置
GOEXPERIMENT=staticlockranking。 默认未开启,此时lockRanStruct是一个空结构体。lockWithRank()等效于lock()
啥意思啊?按照文档设计顺序,文档是啥,文档顺序是啥?
其实这里是一种非常机翻的说法,他其实说的是在go的配置中启动GOEXPERIMENT=staticlockranking,就会按照一定的顺序检查锁,如果锁不是按照这个顺序进行了,就会出现死锁的情况,那么就会抛出throw(在runtime包内部很多错误是throw,不是panic,throw方法并没有暴露给用户使用,用户只能用recover接panic,也就说用户无法处理throw错误,项目会直接崩掉)
那这个顺序是哪来的?
这个顺序其实是已经规定好的,当然是go语言的开发人员提交的,提交这个changes的地址是https://go-review.googlesource.com/c/go/+/207619
他这个顺序其实是一个map,一个已经规定好的map,lockPartialOrder,位置是runtime包中的lockrank.go
var lockPartialOrder [][]lockRank = [][]lockRank{lockRankSysmon: {},lockRankScavenge: {lockRankSysmon},lockRankForcegc: {lockRankSysmon},lockRankDefer: {},lockRankSweepWaiters: {},lockRankAssistQueue: {},lockRankSweep: {},lockRankPollDesc: {},lockRankCpuprof: {},lockRankSched: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof},lockRankAllg: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched},lockRankAllp: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched},lockRankTimers: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllp, lockRankTimers},lockRankNetpollInit: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllp, lockRankTimers},lockRankHchan: {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankHchan},lockRankNotifyList: {},lockRankSudog: {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankHchan, lockRankNotifyList},lockRankRwmutexW: {},lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},lockRankRoot: {},lockRankItab: {},lockRankReflectOffs: {lockRankItab},lockRankUserArenaState: {},lockRankTraceBuf: {lockRankSysmon, lockRankScavenge},lockRankTraceStrings: {lockRankSysmon, lockRankScavenge, lockRankTraceBuf},lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankProfInsert: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankProfBlock: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankProfMemActive: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},lockRankProfMemFuture: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankHchan, lockRankNotifyList, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankProfMemActive},lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture},lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankRwmutexW, lockRankRwmutexR, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},lockRankStackLarge: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},lockRankHchanLeaf: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankHchanLeaf},lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankSudog, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankMspanSpecial, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankSudog, lockRankRwmutexW, lockRankRwmutexR, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankMspanSpecial, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans},lockRankGlobalAlloc: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankSudog, lockRankRwmutexW, lockRankRwmutexR, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankMheapSpecial, lockRankMspanSpecial, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankSudog, lockRankRwmutexW, lockRankRwmutexR, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankMspanSpecial, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},lockRankTraceStackTab: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankNetpollInit, lockRankHchan, lockRankNotifyList, lockRankSudog, lockRankRwmutexW, lockRankRwmutexR, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankGcBitsArenas, lockRankMspanSpecial, lockRankSpanSetSpine, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankTrace},lockRankPanic: {},lockRankDeadlock: {lockRankPanic, lockRankDeadlock},
}
其实这玩意称之为“文档”多少有点不太直观,但是你知道是什么意思就行,不必纠结这个命名,很多命名有一定的历史因素或者直译不够信雅达,追求这个考古结果太浪费时间
那这个顺序是怎么验证的?
其实验证这个顺序的方法也不复杂,就在runtime/lockrank_on.go文件里的checkRanks方法里
func checkRanks(gp *g, prevRank, rank lockRank) {rankOK := falseif rank < prevRank {// If rank < prevRank, then we definitely have a rank errorrankOK = false} else if rank == lockRankLeafRank {// If new lock is a leaf lock, then the preceding lock can// be anything except another leaf lock.rankOK = prevRank < lockRankLeafRank} else {// We've now verified the total lock ranking, but we// also enforce the partial ordering specified by// lockPartialOrder as well. Two locks with the same rank// can only be acquired at the same time if explicitly// listed in the lockPartialOrder table.list := lockPartialOrder[rank]for _, entry := range list {if entry == prevRank {rankOK = truebreak}}}if !rankOK {printlock()println(gp.m.procid, " ======")printHeldLocks(gp)throw("lock ordering problem")}
}
不知道这个有啥影响么?
没有,不开启GOEXPERIMENT=staticlockranking 都不用关心这个问题,不看源码甚至不知道这个玩意,不必太在意,看到了当个乐子就行
再看下key:
key的实现方式有两种
runtime/lock_futex.go 文件里的futex实现
//go:build dragonfly || freebsd || linux
主要是dragonfly,FreeBSD,linux 系统;
另一个就是 runtime/lock_sema.go 文件里的 sema实现
//go:build aix || darwin || netbsd || openbsd || plan9 || solaris || windows
主要是 aix , darwin , netbsd , openbsd , plan9 , solaris , windows系统
但是实现起来也是大差不差的。
以linux的为例,毕竟日常开发还是linux的项目比较多。
首先,锁的状态有三种
const (mutex_unlocked = 0mutex_locked = 1mutex_sleeping = 2
- mutex_unlocked = 没有锁
- mutex_locked = 锁了
- mutex_sleeping = 表示有线程调用futexsleep阻塞了
然后看lock方法,这个是获取锁的方法
func lock2(l *mutex) {// 获取当前运行该方法的协程Ggp := getg()// 锁都是负数了,出问题了,报错,throw扔出去if gp.m.locks < 0 {throw("runtime·lock: lock count")}// 当前协程G绑定的M上的lock计数+1,不懂的去看GMP结构gp.m.locks++// 资源比较空闲时候,第一次请求锁就成功了,直接返回,表示获取锁成功// Xchg直接交换值,没有CAS操作,Xchg比较简单,理论上更快,Cas还要做值对比,Xchg更适合去抢锁v := atomic.Xchg(key32(&l.key), mutex_locked)if v == mutex_unlocked {return}// 大部分情况下,你获取是失败的,毕竟加锁的场景就是高并发引起的冲突,不然你加个毛的锁// 当v是mutex_unlock和mutex_sleeping的时候,也就说加锁没有成功// 修改名称把状态改成wait——等待wait := v// 自旋次数,如果ncpu也就是cpu核心数大于1,说明是多核cpu,那么就自旋等待下,active_spin实际上是4,那就是自旋4次,至于为什么是4,我没深究spin := 0if ncpu > 1 {// spin是spinning的意思“旋转的”,你打红警的时候盖特机炮的台词就有spinspin = active_spin}for {// 尝试获取锁for i := 0; i < spin; i++ {for l.key == mutex_unlocked {// Cas操作,获取锁。这里的wait的值第一次是上面传入的,第二次则是从for循环末尾拿到的if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {return}}// 这个方法其实是底层调用了CPU的PAUSE指令,意在优化自旋等待的效率,主要是针对赛扬和志强cpu的procyield(active_spin_cnt)}// passive_spin = 1,passive -- 被动的,被动自旋,就是说上面4次自旋都没拿到,再给你一次机会,让你再获取一次锁,所以整个获取锁的自旋次数是 4 + 1for i := 0; i < passive_spin; i++ {for l.key == mutex_unlocked {// 同样的CAS操作获取锁if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {return}}// 让出cpuosyield()}// 切换锁的状态为sleeping,xchg返回原来的值v = atomic.Xchg(key32(&l.key), mutex_sleeping)// 如果原来的值是mutex_unlocked,也就说无锁,那么mutex_sleeping 本身就算拿到锁了if v == mutex_unlocked {return}// 重新设定wait值为mutex_sleeping为下次循环做准备wait = mutex_sleeping// futexsleep调用futex函数进入睡眠。futexsleep(key32(&l.key), mutex_sleeping, -1)}
}
最后看unlock方法,这个是解锁的方法
func unlock2(l *mutex) {// 设置 l.key = mutex_unlocked。v是旧值v := atomic.Xchg(key32(&l.key), mutex_unlocked)// 如果已经是unlocked 你还执行解锁,那么就抛出throw异常if v == mutex_unlocked {throw("unlock of unlocked lock")}// 如果旧状态是sleeping,说明已经有其他协程在等待这个锁,处于sleep状态,这时候解锁的时候,要把那个sleep的协程唤醒if v == mutex_sleeping {// 执行futexwakeupfutexwakeup(key32(&l.key), 1)}// 获取当前的goroutinegp := getg()// 当前g所属的M的锁计数器减一gp.m.locks--if gp.m.locks < 0 {throw("runtime·unlock: lock count")}// m所有的锁已经释放且g本身的preempt位在解锁(unlock)之前就被被标记为true,说明该g可以被抢占了if gp.m.locks == 0 && gp.preempt { // 既然需要被抢占,那么就要设置stackguard0位置为stackPreempt,手动标记为需要检查栈溢出,当调度器检查到栈溢出的时候会根据Goroutine的标记进行相应处理,这里就是减产preempt并执行抢占gp.stackguard0 = stackPreempt}
}
大致就是这样了
相关文章:
go中runtime包里面的mutex是什么?runtime.mutex解析
其实在看go源码的时候,发现除了sync包里有个mutex以外,runtime包里也有一个mutex,这个mutex在runtime很多地方都在用。 这个runtime包里面的mutex的结构如下: 目录: /runtime/runtime2.go 代码: type mutex struct …...
VScode 调试python程序,debug状态闪断问题的解决方法
0. Few words 之前一直在VSCode中debug C和Python的程序没出过闪断的问题,但是最近在另一台电脑上debug,同样的方法,设置launch.json和CMakeList加debug状态等等操作,如我另一篇blog写的一样,可以点这里查看。 但是&a…...
飞桨中的李宏毅课程中的第一个项目——PM2.5的预测
所谓的激活函数,就是李宏毅老师讲到的sigmoid函数 和 hard sigmoid函数 ,ReLU函数那些 现在一点点慢慢探索,会成为日后想都做不到的经历,当你啥也不会的时候,才是慢慢享受探索的过程。 有一说一,用chatGP…...
Qt---对话框 事件处理 如何发布自己写的软件
目录 一、对话框 1.1 消息对话框(QMessageBox) 1> 消息对话框提供了一个模态的对话框,用来提示用户信息,或者询问用户问题并得到回答 2> 基于属性版本的API 3> 基于静态成员函数版本 4> 对话框案例 1、ui界面 …...
【C++】C++ 引用详解 ⑩ ( 常量引用案例 )
文章目录 一、常量引用语法1、语法简介2、常引用语法示例 二、常量引用语法1、int 类型常量引用示例2、结构体类型常量引用示例 在 C 语言中 , 常量引用 是 引用类型 的一种 ; 借助 常量引用 , 可以将一个变量引用 作为实参 传递给一个函数形参 , 同时保证该值不会在函数内部被…...
React原理 - React Reconciliation-下
目录 Fiber Reconciler 【react v16.13.1】 React Fiber需要解决的问题 React Fiber的数据结构 时间分片 Fiber Reconciler 的调度 双缓冲 池概念 小节 练习 Fiber Reconciler 【react v16.13.1】 Fiber 协调 优化了栈协调的事务性弊端引起的卡顿 React Fiber需要解决…...
YOLOv8超参数调优教程! 使用Ray Tune进行高效的超参数调优!
原创文章为博主个人所有,未经授权不得转载、摘编、倒卖、洗稿或利用其它方式使用上述作品。违反上述声明者,本站将追求其相关法律责任。 这篇博文带大家玩点新的东西,也是一直以来困扰大家最大的问题—超参数调优! 之前的 YOLOv5 我使用遗传算法做过很多次调优,实验一跑就…...
JVM运行时数据区
文章目录 JVM内存结构图1、运行时数据区域JDK 1.7JDK 1.81. 线程栈(虚拟机栈)2. 本地方法栈3. 程序计数器4. 方法区(元空间)5. 堆6、运行时常量池(Runtime Constant Pool)7、直接内存(Direct Me…...
第七章,相似矩阵及其应用,3-二次型、合同矩阵与合同变换
第七章,相似矩阵及其应用,3-二次型、合同矩阵与合同变换 二次型相关概念二次型二次型的标准形和规范形表示形式 合同矩阵与合同变换定义 合同合同矩阵的性质等价、相似、合同三种关系的对比等价相似合同 玩转线性代数(38)二次型概念、合同矩阵与合同变换…...
css学习7(盒子模型)
1、盒子模型图: Margin(外边距) - 清除边框外的区域,外边距是透明的。Border(边框) - 围绕在内边距和内容外的边框。Padding(内边距) - 清除内容周围的区域,内边距是透明的。Content(内容) - 盒子的内容,显示文本和图像。 <!DO…...
C++笔记之临时变量与临时对象与匿名对象
C笔记之临时变量与临时对象与匿名对象 code review! 文章目录 C笔记之临时变量与临时对象与匿名对象1.C中的临时变量指的是什么?2.C中的临时对象指的是什么?3.C中临时对象的作用是什么?什么时候要用到临时对象?4.给我列举具体的例子说明临…...
缓存技术(缓存穿透,缓存雪崩,缓存击穿)
大家好 , 我是苏麟 , 今天聊一聊缓存 . 这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员 如果想要了解更详细的资料去黑马官网查看 前言:什么是缓存? 缓存,就是数据交换的 缓冲区 (称作Cache [ kʃ ] ),俗称的缓存就是缓冲区内的数据,是存贮数据的…...
实操教程 | 触发器实现 Apache DolphinScheduler 失败钉钉自动告警
作者 | sqlboy-yuzhenc 背景介绍 在实际应用中,我们经常需要将特定的任务通知给特定的人,虽然 Apache DolphinScheduler 在安全中心提供了告警组和告警实例,但是配置起来相对复杂,并且还需要在定时调度时指定告警组。通过这篇文…...
以“迅”防“汛”!5G视频快线筑牢防汛“安全堤”
近期,西安多地突发山洪泥石流灾害。防洪救灾刻不容缓,为进一步做好防汛工作,加强防洪调度监管,切实保障群众的生命财产安全,当地政府管理部门亟需拓展智能化技术,通过人防技防双保障提升防灾救灾应急处置能…...
jmeter 性能测试工具的使用(Web性能测试)
1、下载 该软件不用安装,直接解压打开即可使用。 2、使用 这里就在win下进行,图形界面较为方便 在目录apache-jmeter-2.13\bin 下可以见到一个jmeter.bat文件,双击此文件,即看到JMeter控制面板。主界面如下: 3、创…...
springboot整合第三方技术邮件系统
springboot整合第三方技术邮件系统,发邮件是java程序的基本操作,springboot整合javamail其实就是简化开发。不熟悉邮件的小伙伴可以先学习完javamail的基础操作,再来看这一部分内容才能感触到springboot整合javamail究竟简化了哪些操作。简化…...
Python入门学习——Day2-变量和数据类型
一、Python 变量 在Python中,变量用于保存数据,方便程序对数据的处理和操作。下面是关于Python变量的一些重要概念: 变量命名规则: 变量名由字母、数字和下划线组成。变量名可以以字母或下划线开头,但不能以数字开头…...
Graylog 更改显示的时区(Display timezone)
每个 Graylog 用户都可以配置他们的显示时区。 这会更改用于查看日志消息的时区,但不会更改日志消息的原始时区。 默认情况下,Graylog 显示 UTC 格式的所有时间戳(也就是 0:00)。就像是下面这样 非Admin账户要更改时区࿱…...
【网络安全防护】上海道宁与Bitdefender帮助您构建弹性网络并降低安全运营成本
在网络的世界中 风险变得更加常见与复杂 企业需要从网络安全转向网络弹性 复杂的网络攻击已非常普遍 在面临攻击时 企业如何保持业务连续性? Bitdefender GravityZone将 风险分析、安全加固、威胁预防 检测和响应功能相结合 帮助您构建弹性网络 并降低安全…...
文心一言 VS CHATGPT
由于近几天来,我的手机短信不断收到百度公司对于“文心一言”大模型的体验邀请(真是不胜其烦)!!所以我就抱着试试看的态度点开了文心一言的链接:文心一言 目前看来,有以下两点与chatgpt是有比较…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
