当前位置: 首页 > news >正文

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源码的时候&#xff0c;发现除了sync包里有个mutex以外&#xff0c;runtime包里也有一个mutex&#xff0c;这个mutex在runtime很多地方都在用。 这个runtime包里面的mutex的结构如下&#xff1a; 目录: /runtime/runtime2.go 代码&#xff1a; type mutex struct …...

VScode 调试python程序,debug状态闪断问题的解决方法

0. Few words 之前一直在VSCode中debug C和Python的程序没出过闪断的问题&#xff0c;但是最近在另一台电脑上debug&#xff0c;同样的方法&#xff0c;设置launch.json和CMakeList加debug状态等等操作&#xff0c;如我另一篇blog写的一样&#xff0c;可以点这里查看。 但是&a…...

飞桨中的李宏毅课程中的第一个项目——PM2.5的预测

所谓的激活函数&#xff0c;就是李宏毅老师讲到的sigmoid函数 和 hard sigmoid函数 &#xff0c;ReLU函数那些 现在一点点慢慢探索&#xff0c;会成为日后想都做不到的经历&#xff0c;当你啥也不会的时候&#xff0c;才是慢慢享受探索的过程。 有一说一&#xff0c;用chatGP…...

Qt---对话框 事件处理 如何发布自己写的软件

目录 一、对话框 1.1 消息对话框&#xff08;QMessageBox&#xff09; 1> 消息对话框提供了一个模态的对话框&#xff0c;用来提示用户信息&#xff0c;或者询问用户问题并得到回答 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. 线程栈&#xff08;虚拟机栈&#xff09;2. 本地方法栈3. 程序计数器4. 方法区&#xff08;元空间&#xff09;5. 堆6、运行时常量池&#xff08;Runtime Constant Pool&#xff09;7、直接内存&#xff08;Direct Me…...

第七章,相似矩阵及其应用,3-二次型、合同矩阵与合同变换

第七章&#xff0c;相似矩阵及其应用&#xff0c;3-二次型、合同矩阵与合同变换 二次型相关概念二次型二次型的标准形和规范形表示形式 合同矩阵与合同变换定义 合同合同矩阵的性质等价、相似、合同三种关系的对比等价相似合同 玩转线性代数(38)二次型概念、合同矩阵与合同变换…...

css学习7(盒子模型)

1、盒子模型图&#xff1a; Margin(外边距) - 清除边框外的区域&#xff0c;外边距是透明的。Border(边框) - 围绕在内边距和内容外的边框。Padding(内边距) - 清除内容周围的区域&#xff0c;内边距是透明的。Content(内容) - 盒子的内容&#xff0c;显示文本和图像。 <!DO…...

C++笔记之临时变量与临时对象与匿名对象

C笔记之临时变量与临时对象与匿名对象 code review! 文章目录 C笔记之临时变量与临时对象与匿名对象1.C中的临时变量指的是什么&#xff1f;2.C中的临时对象指的是什么&#xff1f;3.C中临时对象的作用是什么&#xff1f;什么时候要用到临时对象?4.给我列举具体的例子说明临…...

缓存技术(缓存穿透,缓存雪崩,缓存击穿)

大家好 , 我是苏麟 , 今天聊一聊缓存 . 这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员 如果想要了解更详细的资料去黑马官网查看 前言:什么是缓存? 缓存,就是数据交换的 缓冲区 (称作Cache [ kʃ ] ),俗称的缓存就是缓冲区内的数据,是存贮数据的…...

实操教程 | 触发器实现 Apache DolphinScheduler 失败钉钉自动告警

作者 | sqlboy-yuzhenc 背景介绍 在实际应用中&#xff0c;我们经常需要将特定的任务通知给特定的人&#xff0c;虽然 Apache DolphinScheduler 在安全中心提供了告警组和告警实例&#xff0c;但是配置起来相对复杂&#xff0c;并且还需要在定时调度时指定告警组。通过这篇文…...

以“迅”防“汛”!5G视频快线筑牢防汛“安全堤”

近期&#xff0c;西安多地突发山洪泥石流灾害。防洪救灾刻不容缓&#xff0c;为进一步做好防汛工作&#xff0c;加强防洪调度监管&#xff0c;切实保障群众的生命财产安全&#xff0c;当地政府管理部门亟需拓展智能化技术&#xff0c;通过人防技防双保障提升防灾救灾应急处置能…...

jmeter 性能测试工具的使用(Web性能测试)

1、下载 该软件不用安装&#xff0c;直接解压打开即可使用。 2、使用 这里就在win下进行&#xff0c;图形界面较为方便   在目录apache-jmeter-2.13\bin 下可以见到一个jmeter.bat文件&#xff0c;双击此文件&#xff0c;即看到JMeter控制面板。主界面如下&#xff1a; 3、创…...

springboot整合第三方技术邮件系统

springboot整合第三方技术邮件系统&#xff0c;发邮件是java程序的基本操作&#xff0c;springboot整合javamail其实就是简化开发。不熟悉邮件的小伙伴可以先学习完javamail的基础操作&#xff0c;再来看这一部分内容才能感触到springboot整合javamail究竟简化了哪些操作。简化…...

Python入门学习——Day2-变量和数据类型

一、Python 变量 在Python中&#xff0c;变量用于保存数据&#xff0c;方便程序对数据的处理和操作。下面是关于Python变量的一些重要概念&#xff1a; 变量命名规则&#xff1a; 变量名由字母、数字和下划线组成。变量名可以以字母或下划线开头&#xff0c;但不能以数字开头…...

Graylog 更改显示的时区(Display timezone)

每个 Graylog 用户都可以配置他们的显示时区。 这会更改用于查看日志消息的时区&#xff0c;但不会更改日志消息的原始时区。 默认情况下&#xff0c;Graylog 显示 UTC 格式的所有时间戳&#xff08;也就是 0:00&#xff09;。就像是下面这样 非Admin账户要更改时区&#xff1…...

【网络安全防护】上海道宁与Bitdefender帮助您构建弹性网络并降低安全运营成本

在网络的世界中 风险变得更加常见与复杂 企业需要从网络安全转向网络弹性 复杂的网络攻击已非常普遍 在面临攻击时 企业如何保持业务连续性&#xff1f; Bitdefender GravityZone将 风险分析、安全加固、威胁预防 检测和响应功能相结合 帮助您构建弹性网络 并降低安全…...

文心一言 VS CHATGPT

由于近几天来&#xff0c;我的手机短信不断收到百度公司对于“文心一言”大模型的体验邀请&#xff08;真是不胜其烦&#xff09;&#xff01;&#xff01;所以我就抱着试试看的态度点开了文心一言的链接&#xff1a;文心一言 目前看来&#xff0c;有以下两点与chatgpt是有比较…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...