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

Go语言读写锁(RWMutex)底层原理详解

Go语言读写锁(RWMutex)底层原理详解

概述

Go语言的sync.RWMutex是一种读写锁,允许多个读操作同时进行,但写操作是互斥的。这种锁机制在读多写少的场景下能显著提高并发性能。底层通过互斥锁和原子计数器实现复杂的并发控制。

核心数据结构

type rwmutex struct {rLock      mutex    // 保护读操作相关的数据(readers, writer)readers    muintptr // 等待读操作的队列wLock      mutex    // 控制写操作的互斥锁writer     muintptr // 等待完成读操作的写操作readerCount atomic.Int32 // 当前有多少个正在进行的读操作readerWait  atomic.Int32 // 写操作需要等待的读操作的数量readerPass  int32     // 读通过计数
}

字段说明

  • rLock: 保护读操作相关的数据(readers, writer队列)
  • readers: 等待读操作的队列(muintptr链表结构)
  • wLock: 控制写操作的互斥锁,确保写操作互斥
  • writer: 等待完成读操作的写操作指针
  • readerCount: 当前有多少个正在进行的读操作,关键设计:负数表示有写操作竞争
  • readerWait: 写操作需要等待的读操作的数量
  • readerPass: 写操作完成后允许通过的读操作数

状态转换机制

1. rlock() 获取读锁流程

rlock()操作流程:

func (rw *rwmutex) rlock() {// 增加当前读操作的计数,如果 +1 还小于0,说明目前有写锁竞争if rw.readerCount.Add(1) < 0 {// 如果有写操作等待,则当前读操作需要挂起,排队等待写操作完成systemstack(func() {// 获取rLock锁lock(&rw.rLock)if rw.readerPass > 0 {// 如果写操作已经完成,跳过当前读操作rw.readerPass -= 1unlock(&rw.rLock)} else {// 将当前读操作加入等待队列,等待写操作释放锁m := getg().mm.schedlink = rw.readersrw.readers.set(m)unlock(&rw.rLock)// 当前读操作挂起,等待写操作唤醒notesleep(&m.park)noteclear(&m.park)}})}
}

关键点:

  • 原子操作递增readerCount
  • 如果结果为负数,说明有写者在等待,当前读者需要阻塞
  • 这种设计实现了写者优先的策略

2. runlock() 解锁读锁流程

runlock()操作流程:

func (rw *rwmutex) runlock() {// 如果r小于0说明此时有writer竞争if r := rw.readerCount.Add(-1); r < 0 {if r+1 == 0 || r+1 == -rwmutexMaxReaders {throw("runlock of unlocked rwmutex")}// 将等待reader的计数减1,如果值==0,说明读等待都处理完了// 此时需要唤醒写等待if rw.readerWait.Add(-1) == 0 {lock(&rw.rLock)w := rw.writer.ptr()if w != nil {notewakeup(&w.park)}unlock(&rw.rLock)}}
}

关键点:

  • 原子操作递减readerCount
  • 如果递减后为负数,说明有写者在等待
  • readerWait减到0时,唤醒等待的写者

3. lock() 获取写锁流程

lock()操作流程:

const rwmutexMaxReaders = 1 << 30func (rw *rwmutex) lock() {// 获取写互斥锁,确保只有一个写操作可以执行lock(&rw.wLock)m := getg().m// 将readerCount - 最大读锁数,肯定得到一个负数// 不会丢失当前正在进行的读操作数量,又可以将值设置为负数r := rw.readerCount.Add(-rwmutexMaxReaders) + rwmutexMaxReaders// 获取读锁lock(&rw.rLock)// 如果有读操作正在进行,写操作需要等待它们完成if r != 0 && rw.readerWait.Add(r) != 0 {// 等待读操作完成后才能执行写操作systemstack(func() {// 设置当前写操作为等待状态rw.writer.set(m)unlock(&rw.rLock)// 当前写操作挂起,等待读操作唤醒notesleep(&m.park)noteclear(&m.park)})} else {unlock(&rw.rLock)}
}

关键点:

  • 先获取基础互斥锁w
  • readerCount减去一个很大的数(rwmutexMaxReaders),使其变为负数
  • 等待现有读者完成(通过readerWait计数)

4. unlock() 解锁写锁流程

unlock()操作流程:

func (rw *rwmutex) unlock() {// 将readerCount复原,表示当前写操作已经完成r := rw.readerCount.Add(rwmutexMaxReaders)if r >= rwmutexMaxReaders {// 如果没有锁被持有,抛出异常throw("unlock of unlocked rwmutex")}// 获取rLock锁,操作读者队列lock(&rw.rLock)// 遍历并唤醒所有在读者队列中的等待操作for rw.readers.ptr() != nil {reader := rw.readers.ptr()rw.readers = reader.schedlinkreader.schedlink.set(nil)notewakeup(&reader.park)r -= 1}unlock(&rw.rLock)// 释放写锁,允许其他写操作进行unlock(&rw.wLock)
}

关键点:

  • readerCount恢复为正数
  • 唤醒所有等待的读者
  • 最后释放基础互斥锁

优先级策略

写者优先机制

Go的RWMutex实现了写者优先的策略,这是通过以下机制实现的:

  1. 负数标记:当写者到来时,将readerCount设置为负数
  2. 新读者阻塞:新来的读者发现readerCount为负数时会阻塞
  3. 写者等待:写者会等待现有读者完成,但不会让新读者"插队"

避免饥饿

这种设计避免了写者饥饿问题:

  • 如果不断有新读者到来,写者可能会永远等待
  • 通过负数标记,新读者会被阻塞,确保写者最终能获得锁

并发控制流程

读操作并发

graph TDA[Reader1请求读锁] --> B[readerCount++]C[Reader2请求读锁] --> D[readerCount++]B --> E[Reader1获得读锁]D --> F[Reader2获得读锁]E --> G[Reader1释放读锁]F --> H[Reader2释放读锁]G --> I[readerCount--]H --> J[readerCount--]

读写互斥

graph TDA[Reader持有读锁] --> B[Writer请求写锁]B --> C[readerCount设为负数]C --> D[Writer等待]A --> E[Reader释放读锁]E --> F[readerCount--]F --> G[检查readerWait]G --> H[唤醒Writer]H --> I[Writer获得写锁]

性能特点

优点

  1. 高并发读:多个读操作可以同时进行
  2. 写者优先:避免写者饥饿
  3. 公平性:在读写竞争中保持相对公平

缺点

  1. 写操作开销:写操作需要等待所有读者完成
  2. 内存开销:需要维护多个计数器和信号量
  3. 复杂度:实现逻辑相对复杂

使用场景

适合场景

  • 读多写少:如配置文件读取、缓存查询
  • 读操作耗时短:快速读取,避免长时间持有锁
  • 写操作不频繁:偶尔的更新操作

不适合场景

  • 写操作频繁:会导致读者频繁阻塞
  • 读操作耗时:长时间持有读锁会影响写操作
  • 需要严格公平:某些场景可能需要更复杂的公平策略

总结

Go语言的RWMutex通过巧妙的设计实现了高效的读写锁机制:

  1. 原子操作:使用原子操作保证计数器的准确性
  2. 信号量机制:通过信号量实现等待/唤醒机制
  3. 负数标记:用负数表示写者等待状态
  4. 写者优先:避免写者饥饿问题

这种设计在读多写少的场景下能显著提高并发性能,是Go并发编程中的重要工具。

注意:在实际使用中,要避免在持有锁时进行耗时操作,以免影响其他goroutine的执行。同时,要确保锁的正确释放,避免死锁。

相关文章:

Go语言读写锁(RWMutex)底层原理详解

Go语言读写锁(RWMutex)底层原理详解 概述 Go语言的sync.RWMutex是一种读写锁,允许多个读操作同时进行,但写操作是互斥的。这种锁机制在读多写少的场景下能显著提高并发性能。底层通过互斥锁和原子计数器实现复杂的并发控制。 核心数据结构 type rwmutex struct {rLock m…...

【GitHub每日速递】无需提示词!Nano Bananary香蕉超市:AI绘画玩法多到停不下来

原文:【GitHub每日速递】无需提示词!Nano Bananary香蕉超市:AI绘画玩法多到停不下来 AutoGPT来袭!搭建、部署、运行AI智能体全攻略揭秘 AutoGPT 是一个基于自主任务执行的AI代理工具。简单讲,它能让AI自动拆解目标并执行一系列操作来完成任务,无需持续人工干预。适用人群…...

小题狂练 (J)

solset-J\[\newcommand{\diag}{\operatorname{diag}} \]目录 目录[AGC070B] Odd Namori[JOI Open 2025] 冒泡排序机 / Bubble Sort Machine[AGC039F] Min Product Sum[AGC070B] Odd NamoriMatrix-Tree 定理:给一张带权有向图 \(G\),求 \(G\) 所有以 \(1\) 为根的内向生成树边…...

Drift数据库开发实战:类型安全的SQLite解决方案

Drift数据库开发实战:类型安全的SQLite解决方案本文基于BeeCount(蜜蜂记账)项目的实际开发经验,深入探讨如何使用Drift构建类型安全、高性能的Flutter数据库层。项目背景 BeeCount(蜜蜂记账)是一款开源、简洁、无广告的个人记账应用。所有财务数据完全由用户掌控,支持本地存…...

DELPHI FireDAC连接EXCEL文件

重要提示: xls后缀的文件与xlsx后缀的文件,连接方法不一样. 可以使用代码来实现:FDConnection1.Connected := false;FDConnection1.Params.Clear;FDConnection1.DriverName := ODBC;FDConnection1.Params.Values[DriverID] := ODBC;FDConnection1.Params.Values[ODBCDriver] :=…...

读人形机器人09教育行业

读人形机器人09教育行业1. 教育行业 1.1. 教育是社会进步的基石,是指引后代走向启蒙与创新的明灯 1.2. 人形机器人通过使学习互动化、沉浸化、趣味化,革新了教学方法 1.3. 借助技术创造兼具教育性与吸引力的体验,培养学生成为主动学习者和批判性思考者 2. 个性化学习体验 2.…...

PHP判断字符串是否包含中文

function hasChinese($str) { return preg_match(/[\x{4e00}-\x{9fa5}]/u, $str);} // 使用示例$string = "Hello 你好";if (hasChinese($string)) { echo "字符串包含中文";} else { echo "字符串不包含中文";}每天进步一点点...

当我们红尘作伴,活得潇潇洒洒

为了证明我是真的睡不着而非摆到凌晨三点,先来一点正经东西。平面等腰直角三角形加,查询矩形和。经典问题,但我刚刚才会。考虑矩形加矩形和是咋做的,通过一堆拆拆拆把 4-side 变成 2-side,然后扫描线扫掉一维,数据结构维护另一维。那等腰直角三角形肯定也要拆拆拆。认为下…...

诡异的mysql8的问题

同样是使用 mysql8的镜像 在其他三台服务器上能正常执行druid:initial-size: 5min-idle: 5max-active: 20max-wait: 60000# 调整为 1800000 毫秒 (30 分钟),需大于数据库 wait_timeoutmin-evictable-idle-time-millis: 1800000# 调整检查间隔为 120000 毫秒 (2 分钟)time-betwe…...

二叉树理论

满二叉树:只有度数为0或者2的节点,并且度数为0的节点在同一层;完全二叉树 除了底层节点可能没填满以外其他都填满了,并且最下面一层的节点都集中在该层最左边的若干位置。 之前我们刚刚讲过优先级队列其实是一个堆,堆就是一棵完全二叉树,同时保证父子节点的顺序关系。 二…...

支付中心的熔断降级要怎么做

下面我会把支付中心在流量骤增 / 下游通道故障时的熔断与降级策略拆成(1)原则与常见策略,(2) 业务级降级/路由策略,(3) 具体落地组件(行业实践与参考),以及(4)可直接落地的 Java 示例(使用 Resilience4j + fallback + 速率限制 + 隔离)。 1) 基本原则(5 条行业共识…...

协议版iM蓝号检测,批量筛选iMessages数据,无痕检测是否开启iMessage服务

一、实现iMessage数据检测的两种方式:1.人工筛选,将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。2…...

栈和队列总结

栈和队列理论C++中stack,queue 是容器么? 我们使用的stack,queue是属于那个版本的STL? 我们使用的STL中stack,queue是如何实现的? stack,queue 提供迭代器来遍历空间么?stack和queue是STL中的容器适配器,不是类似list,vector那样的容器; 容器适配器本质上是基于底层真…...

工业互联网认知实训台-一句话介绍

工业互联网认知实训台主要由传感器、PLC控制器、工业以太网设备、人机界面(HMI)、步进电机和伺服电机等设备组成。步进电机:通过电脉冲信号控制电机每步旋转固定角度,结构简单、成本低,适合精确定位,但效率较低且可能失步。实训台中使用PLC(如1212C系列)通过脉冲信号控…...

1

<meta name="description" content="加载中... 如白屏请[ 点击刷新页面 ]"> <meta property="og:description" content="加载中... 如白屏请[ 点击刷新页面 ]"> <meta http-equiv="Cache-Control" content=&…...

湾区杯 SilentMiner WP

攻击者的ip地址查看文件 /var/log/btmp 发现短时间内大量登录,可确定攻击者 ip 为 192.168.145.131 lastb -f /var/log/btmp192.168.145.131攻击者共进行多少次ssh口令爆破失败?根据 /var/log/btmp 文件计数 lastb -f btmp | grep 192.168.145.131 | wc -l也可以在 /var/log/…...

Python-课后题题目-1.1编程世界初探

1.1编程世界初探(单选题) 1.程序设计语言的主要目的是什么? A让计算机变得更便宜 B使人类能够以高效,清晰,结构化的方式表达计算机逻辑和数据操作 C取代数学和逻辑学 D仅用于编写游戏程序 2.机器语言是由什么组成的? A十进制数字 B英文字母 C二进制代码 D特殊符号 3.汇…...

Python-课后题题目-1.2初识python语言

1.2初识python语言(单选题)Python语言最初由谁创建? A.林纳斯托瓦兹 B.吉多范罗苏姆 C.詹姆斯高斯林 D.布雷丹艾奇 Python 0.9.0版本首次发布于哪一年? A.1989 B.1991 C.1994 D.2000 Python 1.0版本引入了以下哪项特性? A.异步编程 B.类型注释 C.循环和异常处理 D.垃圾回收…...

node和npm相关的记录

1 npm install --loglevel verbose 安装的啰嗦模式会打印日志2 3 npm config get registry 查看镜像源信息。 淘宝的镜像源已经关闭了。4 5 #windwos可以安装一个nvm,可以切换node和npm的版本。6 nvm下载地址 https://github.com/coreybutler/nvm-windows/releases7 8 nvm in…...

在Spring boot 中使用@master 设置主从数据库

基础配置 application.ymlspring:  datasource:     master:       url: jdbc:mysql://localhost:3306/master_db       username: root       password: 123456       driver-class-name: com.mysql.cj.jdbc.Driver …...

设计模式-装饰器模式 - MaC

装饰器模式是一种结构型设计模式,它允许在不修改原有对象结构的情况下,动态地给对象添加新的功能。装饰器模式通过创建一个包装对象(装饰器)来包裹真实的对象,从而在运行时扩展对象的功能。 装饰器模式包含以下角色:组件(Component):定义一个对象接口,可以给这些对象动…...

【API接口】最新可用河马短剧接口

最新可用红果短剧接口,支持短剧搜索、短剧详情解析、短剧播放链接解析功能,助您快速构建您的专属短剧客户端 使用之前您需要先去注册下key 申请地址: https://www.52api.cn 接口地址:https://www.52api.cn/api/hm_duanju 返回格式:application/json 请求方式:GET/POST 请…...

第 16 章反射(reflection)

第 16 章反射(reflection)第 16 章反射(reflection) 16.1 一个需求引出反射 16.1.1 请看下面的问题根据配置文件 re.properties 指定信息,创建Cat对象并调用方法hi classfullpath=com.hspedu.Cat method=hi思考:使用现有技术,你能做的吗?这样的需求在学习框架时特别多,即通…...

自我介绍+软工5问

| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/join?id=CfDJ8G33EJ5dWE5OhU_7yPrjq1_EG2G2ljnyYNdPWrrB61TEPdvbX8B-02_mm2lbvSH0zHF0AFJBdSQazCWQtYhdASVnPbQZ7mm4BuFr16ksfoeASRJAr16ktj02s3Qx3JGS33oIuJz021Uout0lNo8pyB8 …...

电容器+动生电动势+自由落体模型

电容器电容为 \(C\),磁感应强度为 \(B\),导体棒长度为 \(L\),质量为 \(m\),重力加速度 \(g\)。 设关于时间 \(t\) 的函数 \(E(t),U(t),Q(t),I(t),v(t),a(t)\)。 \[\begin{cases} E(t)=BLv(t)\\ U(t)=E(t)\\ Q(t)=CU(t)\\ I(t)=Q(t)\\ F(t)=mg-BLI(t)\\ a(t)=v(t)=\dfrac{F(…...

引用(reference)

1.概念 引用是C++对C的一个重要扩充,引用表示给变量起个别名;//类似于linux中的硬链接文件 2.定义引用 数据类型 &引用名 = 引用的目标; 如: int &b = a; & 在C++有三种作用: (1)定义引用时,是引用标识符,表示定义的是一个引用 (2)按位与 & (3)其他任何场…...

设计模式-组合模式 - MaC

什么是组合模式? 组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次关系。组合模式使得客户端对单个对象和组合对象的使用具有一致性。 组合模式包含以下角色:组件(Component):声明组合中对象的接口,适当情况下实现所有类共有…...

【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态

加载中... 如白屏请[点击刷新页面 ]...

tmux 使用教程

1. 什么是 tmux tmux 是一个 终端复用器(terminal multiplexer)。 它允许你在一个终端里运行多个会话(session)、窗口(window)、面板(pane),并且支持:断开与重连:即使 SSH 连接断开,任务仍然继续运行。 多窗口管理:一个终端里像“标签页”一样切换窗口。 分屏功能…...

引用类型

“引用”(reference)是c++的一种新的变量类型,是对C的一个重要补充。它的作用是为变量起一个别名。假如有一个变量a,想给它起一个别名,可以这样写: int a; int &b=a;这就表明了b是a的“引用”,即a的别名。经过这样的声明,使用a或b的作用相同,都代表同一变量。在上…...

CF1237C2

CF1237 C2. Balanced Removals (Harder) 题目描述 这是该问题的更难版本。在本版本中,\(n \le 50\,000\)。 在三维空间中有 \(n\) 个互不相同的点,编号从 \(1\) 到 \(n\)。第 \(i\) 个点的坐标为 \((x_i, y_i, z_i)\)。点的数量 \(n\) 是偶数。 你需要通过一系列 \(\frac{n}{…...

我好像是病了,这几天的黑眼圈越来越重,明明都是按时早睡,但就是睡不够,整天昏昏沉沉,今天甚至一不小心扭伤了腿,坐在队伍旁边,我居然又渐渐睡了过去,尽管周围很吵闹。 我可能是病了,我每天感到有着无数审视的目光向我投来,同伴的漠视,他人的讥讽,上位者的冷眼,我感…...

力扣215. 数组中的第K个最大元素

力扣215. 数组中的第K个最大元素 1.二叉最小堆法:维护一个size为k的最小堆,每次从堆中去除一个比item更小的元素,最后留下的便是最大的k个元素。(nlogn)1 class Solution {2 public:3 int findKthLargest(vector<int>& nums, int k) {4 priority_que…...

linux环境docker离线镜像elasticsearch-7.17.3镜像资源

中国移动云盘下载地址: https://caiyun.139.com/w/i/2pU90TqM2d73i 提取码:ydab 复制内容打开中国移动云盘手机APP,操作更方便 1、准备已安装docker的Linux环境,将文件放到任意目录解压 2、导入镜像命令:docker load -i elasticsearch-7.17.3.tar 3、运行镜像命令:docker…...

Python 降序排序:轻松搞定列表、字典和自定义对象

在 Python 中,降序排序是一个非常常见的需求。无论是对列表、字典还是自定义对象进行排序,Python 都提供了简单而强大的方法来实现降序排序。今天,就让我们一起学习如何在 Python 中实现降序排序,并分享一些实用的技巧和最佳实践。 一、列表的降序排序 (一)使用 sort() 方…...

第02周 预习、实验与作业:Java基础语法2、面向对象入门

集美大学课程实验报告-第02周 预习、实验与作业:Java基础语法2、面向对象入门项目名称 内容课程名称 数据结构班级 网安2413指导教师 郑如滨学生姓名 林沁茹学号 202421336067实验项目名称 第02周 预习、实验与作业:Java基础语法2、面向对象入门上机实践日期上机实践时间 2学…...

part 4

这场感觉就T4比较有意义LCA 结论:三个点两两求 LCA,lca 的编号异或起来是答案(到三个点的距离总和最小的点),且该答案是以其中一点为根时另外两点的 LCA。 所以我们可以得到结论 点 \(p\) 和点 \(q\) 以 \(x\) 为根的 lca 深度是 \(dlca_{p,q} \oplus dlca_{p,x} \oplus d…...

systemctl的service脚本写法

Description=MedicTech Server # 服务描述,可以自定义 After=network.target network-online.target nss-lookup.target [Service] Type=simple # 服务类型,简单后台进程常用 simple User=root # 指定运行服务的用户,根据你的需求修改,非 root 用户更安全 ExecStart=/home/…...

9月份美联储的降息利好

美联储降息利好消息美国8月CPI与就业数据公布:通胀符合预期,失业金人数攀升,市场反应积极北京时间11日晚间,美国劳工统计局及相关机构公布多项关键经济数据,数据表现呈现分化,同时引发金融市场显著波动,具体如下:一、核心经济数据概览通胀数据(CPI):符合市场预期 美…...

口胡记录

我们都会拥有美好的未来——频率也大概就是一天两题的样子,因为我还要做到一周 VP 两场 CF Div2。 这对于一个暑假才开始复健,一年没训的人来说已经很困难了/fn/ll P9753 [CSP-S 2023] 消消乐 Description 给你一个字符串 \(s\),让你求出 \(s\) 的偶回文子串个数。 \(|s|\le…...

Day16内存分析及初始化

图中空白处是关于数组下标越界的报错,调用的数组长度超出被调用数组的长度时程序会报错package array;public class ArrayDemo2 {public static void main(String[] args) {//静态初始化:创建+赋值int [] a = {123,4566,756765,5676,421,442,};System.out.println(a[3]);//前面…...

leveldb源码分析 #1 Slice WriteBatch WriteBatchInternal 【work记录】

日期:2025.9.6(凌晨) 个人总结: perface 是这样的,本来是打算写完之后再整理的,但是感觉自己貌似会懒癌犯了,所以决定还是自己看了哪些内容就都发了吧。 如果自己真的会想整理的话,那就算之前写个过半成品应该也会有心去整理好好总结吧。 为了自己的数据库的水平可以再提…...

欧拉安装

因为 openEuler 22.03 LTS 使用的内核版本是 5.10,所以选择 5.x 内核的选项是最匹配的。...

2025实测:6款主流公众号编辑器大比拼,解决你的排版难题!

在新媒体运营的日常工作中,公众号排版是一项耗时又费力的任务。写作慢、排版耗时、跨平台排版不统一、跨平台发文琐碎、热点跟不动不及时、配图难/侵权风险等问题,常常困扰着我们这些新媒体人。为了找到一款好用的公众号编辑器,我亲测了多款市面上的主流产品。在本文中,我将…...

devc学C语言

之前用的是VS,现在开始用 devc,兼容性更强...

HarmonyOS 5.1手势事件详解

大家好,我是 V 哥。手势事件由绑定手势方法和绑定的手势组成,绑定的手势可以分为单一手势和组合手势两种类型,根据手势的复杂程度进行区分。本文跟着 V 哥一起来探讨手势事件处理。 想要考取鸿蒙认证的小伙伴,请加入V 哥班级获取辅导: https://developer.huawei.com/consu…...

Vue3项目中集成AI对话功能的实战经验分享

ai-suspended-ball-chat组件使用体验摘要 本文分享了Vue3项目中使用ai-suspended-ball-chat组件集成AI对话功能的实践经验。该组件提供悬浮球和独立面板两种模式,支持流式响应、图片上传、语音交互等功能,显著提升了用户体验。通过实际案例展示了在客服系统和代码助手场景中的…...

gulimall出现服务间调用org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose 问题

java.lang.AbstractMethodError: org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(Ljava/lang/String;Lorg/springframework/cloud/client/loadbalancer/Request;)Lorg/springframework/cloud/client/ServiceInstance;A调用B模块出现上面这个问题,…...

Java02课前问题列表

Java02课前问题列表1.方法相关问题 public class Main {static void changeStr(String x) {x = "xyz";}static void changeArr(String[] strs) {for (int i = 0; i < strs.length; i++) {strs[i] = strs[i]+""+i;}}public static void main(String[] ar…...

达梦数据库安装和使用

1、达梦数据库安装地址 https://eco.dameng.com/document/dm/zh-cn/start/install-dm-windows-prepare.html 2、 点击下载3、4、 现在版本只需要点击exe文件56 点击【下一步】如图所示7、 接受授权协议8 如果没有key文件可跳过 如果有点击浏览找到key文件系统自动校验9建议典型…...