读时加写锁,写时加读锁,Eureka可真的会玩

检索增强世界模型(R-WoM)原理与应用实践 世界模型是AI系统理解环境的核心技术,通过构建环境的内部表示实现状态预测和行动规划。传统方法基于RNN或VAE等神经网络,而检索增强世界模型(R-WoM)创新性地引入检索机制,结合外部记忆库提升系统性能。这种架构突破模型参数限制,使AI能像人类一样利用历史经验解决问题,在游戏AI、虚拟助手等场景表现优异。关键技术包括FAISS相似性搜索、分层记忆管理和动态检索策略,其中Transformer编码器和GRU动态模型的组合实现高效环境建模。实践表明,该方法可提升47%的战术多样性,加快32%的应急响应速度。 阅读详情

Eureka服务注册实现类

众所周知,Eureka作为一个服务注册中心,肯定会涉及到服务实例的注册和发现,从而肯定会有服务实例写操作和读操作,这是每个注册中心最基本也是最核心的功能。

AbstractInstanceRegistry

如上图,AbstractInstanceRegistry是注册中心的服务注册核心实现类,这里面保存了服务实例的数据,封装了对于服务实例注册、下线、读取等核心方法。

这里讲解一下这个类比较重要的成员变量

服务注册表

private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry= new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();

注册表就是存储的服务实例的信息。Eureka是使用ConcurrentHashMap来进行保存的。键值是服务的名称,值为服务的每个具体的实例id和实例数据的映射,所以也是一个Map数据结构。InstanceInfo就是每个服务实例的数据的封装对象。

服务的上线、下线、读取其实就是从注册表中读写数据。

最近变动的实例队列

private ConcurrentLinkedQueue<RecentlyChangedItem> recentlyChangedQueue = new ConcurrentLinkedQueue<>();

recentlyChangedQueue保存了最近变动的服务实例的信息。如果有服务实例的变动发生,就会将这个服务实例封装到RecentlyChangedItem中,存到recentlyChangedQueue中。

什么叫服务实例发生了变动。举个例子,比如说,有个服务实例来注册了,这个新添加的实例就是变动的实例。

所以服务注册这个操作就会有两步操作,首先会往注册表中添加这个实例的信息,其次会给这个实例标记为新添加的,然后封装到RecentlyChangedItem中,存到recentlyChangedQueue中。

新增

同样的,服务实例状态的修改、删除(服务实例下线)不仅会操作注册表,同样也会进行标记,封装成一个RecentlyChangedItem并添加到recentlyChangedQueue中。

修改

下线

所以从这分析也可以看出,注册表的写操作同时也会往recentlyChangedQueue中写一条数据,这句话很重要。

后面本文提到的注册表的写操作都包含对recentlyChangedQueue的写操作。

读写锁

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();

读写锁就不用说了,JDK提供的实现。

读写锁的加锁场景

上面说完了AbstractInstanceRegistry比较重要的成员变量,其中就有一个读写锁,也是本文的主题,所以接下来看看哪些操作加读锁,哪些操作加写锁。

加读锁的场景

1、服务注册

register

服务注册就是在注册表中添加一个服务实例的信息,加读锁。

2、服务下线

cancel和internalCancel

服务下线就是在注册表删除这个服务实例的信息,服务下线的方法最后是调用internalCancel实现的,而internalCancel是加的读锁,所以服务实例下线的时候加了读锁。

3、服务驱逐

什么叫服务驱逐,很简单,就是服务端会定时检查每个服务实例是否有向服务端发送心跳,如果服务端超过一定时间没有接收到服务实例的心跳信息,那么就会认为这个服务实例不可用,就会自动将这个服务实例从注册表删除,这就是叫服务驱逐。

服务驱逐是通过evict方法实现的,这个方法最终也是调用服务下线internalCancel方法来实现驱逐的。

所以服务驱逐,其实也是加读锁的,因为最后是调用internalCancel方法来实现的,而internalCancel方法就是加的读锁。

4、更新服务状态

服务实例的状态变动了,进行更新操作,也是加的读锁

5、删除服务状态

将服务的状态删了,也是加的读锁。

这里都是对于注册表的写操作,所以进行这些操作的同时也会往recentlyChangedQueue中写一条数据,只不过方法太长,代码太多,这里就没有截出来。

加写锁的场景

获取增量的服务实例的信息。

getApplicationDeltasFromMultipleRegions

所谓的增量信息,就是返回最近有变动的服务实例,而recentlyChangedQueue刚刚好保存了最近的服务实例的信息,所以这个方法的实现就是遍历recentlyChangedQueue,取出最近有变动的实例,返回。所以保存最近变动的实例,其实是为了增量拉取做准备的。

加锁总结

这里我总结一下读锁和写锁的加锁场景:

  • 加读锁: 服务注册、服务下线、服务驱逐、服务状态的更新和删除
  • 加写锁:获取增量的服务实例的信息

读写锁的加锁疑问

上一节讲了Eureka中加读锁和写锁的场景,有细心的小伙伴可能会有疑问,加读锁的场景主要涉及到服务注册表的增删操作,也就是写操作;而加写锁的场景是一个读的操作。

这不是很奇怪么,不按套路出牌啊,别人都是写时加写锁,读时加读锁,Eureka刚好反过来,属实是真的会玩。

写的时候加的读锁,那么就说明可以同时写,那会不会有线程安全问题呢?

答案是不会有安全问题。

我们以一个服务注册为例。一个服务注册,涉及到注册表的写操作和recentlyChangedQueue的写操作。

注册表本身就是一个ConcurrentHashMap,线程安全的map,注册表的值的Map数据结构,其实也是一个ConcurrentHashMap,如图。

通过源码可以发现,其实也是放入的值也是一个ConcurrentHashMap,所以注册表本身就是线程安全的,所以对于注册表的写操作,本身就是安全的。

再来看一下对于recentlyChangedQueue,它本身就是一个ConcurrentLinkedQueue,并发安全的队列,也是线程安全的。

所以单独对注册表和recentlyChangedQueue的操作,其实是线程安全的。

到这里更加迷糊了,本身就是线程安全的,为什么要加锁呢,而且对于写操作,还加的是读锁,这就导致可以有很多线程同时去写,对于写来说,相当加锁加了个寂寞。

带着疑惑,接着往下看。

Eureka服务实例的拉取方式和hash对比机制

拉取方式

Eureka作为一个注册中心,客户端肯定需要知道服务端道理存了哪些服务实例吧,所以就涉及到了服务的发现,从而涉及到了客户端跟服务端数据的交互方式,pull还是push。如果有不清楚pull和push的机制,可以看一下 RocketMQ的push消费方式实现的太聪明了 这篇文章,里面有交代什么是pull还是push。

那么Eureka到底是pull还是push模式呢?这里我就不再卖关子了,其实是一种pull模式,也就是说客户端会定期从服务端拉取服务实例的数据。并且Eureka提供了两种拉取方式,全量和增量。

1、全量

全量其实很好理解,就是拉取注册表所有的数据。

全量一般发生在客户端启动之后第一次获取注册表的信息的时候,就会全量拉取注册表。还有一种场景也会全量拉取,后面会说。

2、增量

增量,前面在说加写锁的时候提到了,就是获取最近发生变化的实例的信息,也就是recentlyChangedQueue里面的数据。

增量相比于全量拉取的好处就是可以减少资源的浪费,假如全量拉取的时候数据压根就没有变动,那么白白浪费网络资源;但是如果是增量的话,数据没有变动,那么就没有增量信息,就不会有资源的浪费。

在客户端第一次启动的全量拉取之后,定时任务每次拉取的就是增量数据。

增量拉取的hash对比机制

如果是增量拉取,客户端在拉取到增量数据之后会多干两件事:

  • 会将增量信息跟本地缓存的服务实例进行合并
  • 判断合并后的服务的数据跟服务端的数据是不是一样

那么如何去判定客户端的数据跟服务端的数据是不是一样呢?

Eureka是通过一种hash对比的机制来实现的。

当服务端生成增量信息的时候,同时会生成一个代表这一刻全部服务实例的hash值,设置到返回值中,代码如下

所以增量信息返回的数据有两部分,一部分是变动的实例的信息,还有就是这一刻服务端所有的实例信息生成的hash值。

当客户端拉取到增量信息并跟本地原有的老的服务实例合并完增量信息之后,客户端会用相同的方式计算出合并后服务实例的hash值,然后会跟服务端返回的hash值进行对比,如果一样,说明本次增量拉取之后,客户端缓存的服务实例跟服务端一样,如果不一样,说明两边的服务实例的数据不一样。

这就是hash对比机制,通过这个机制来判断增量拉取的时候两边的服务实例数据是不是一样。

hash对比

但是,如果发现了不一样,那么此时客户端就会重新从服务端全量拉取一次服务数据,然后将该次全量拉取的数据设置到本地的缓存中,所以前面说的还有一种全量拉取的场景就在这里,源码如下

重新全量拉取

读写锁的使用揭秘

前面说了增量拉取和hash对比机制,此时我们再回过头仔细分析一下增量信息封装的两步操作:

  • 第一步遍历recentlyChangedQueue,封装增量的实例信息
  • 第二步生成所有服务实例数据对应的hash值,设置到增量信息返回值中

为什么要加锁

假设不加锁,那么对于注册表和recentlyChangedQueue读写都可以同时进行,那么会出现这么一种情况

当获取增量信息的时候,在第一步遍历recentlyChangedQueue时有2个变动的实例,注册表总共有5个实例

当recentlyChangedQueue遍历完之后,还没有进行第二步计算hash值时,此时有服务实例来注册了,由于不加锁,那么可以同时操作注册表和recentlyChangedQueue,于是注册成功之后注册表数据就变成了6个实例,recentlyChangedQueue也会添加一条数据

但是因为recentlyChangedQueue已经遍历完了,此时不会在遍历了,那么刚注册的这个实例在此次获取增量数据时就获取不到了,但是由于计算hash值是通过这一时刻所有的实例数据来计算,那么就会把这个新的实例计算进去了。

这不完犊子了么,增量信息没有,但是全部实例数据的hash值有,那么就会导致客户端在合并增量信息之后计算的hash值跟返回的hash值不一样,就会导致再次全量拉取,白白浪费了本次增量拉取操作。

所以一定要加锁,保证在获取增量数据时,不能对注册表进行改动。

为什么加读写锁而不是synchronized锁

这个其实跟Eureka没多大关系,主要是读写锁和synchronized锁特性决定的。synchronized会使得所有的操作都是串行化,虽然也能解决问题,但是也会导致并发性能降低。

为什么写时加读锁,读时加写锁

现在我们转过来,按照正常的操作,服务注册等写操作加写锁,获取增量的时候加读锁,那么可以不可呢?

其实也是可以的,因为这样注册表写操作和获取的增量信息读操作还是互斥的,那么获取的增量信息还是对的。

那么为什么Eureka要反过来?

写(锁)写(锁)是互斥的。如果注册表写操作加了写锁,那么所有的服务注册、下线、状态更新都会串行执行,并发性能就会降低,所以对于注册表写操作加了读锁,可以提高写的性能。

但是,如果获取的增量读的操作加了写锁,那岂不是读操作都串行化了,那么读的性能不是会变低么?而且注册中心其实是一个读多写少的场景,为了提升写的性能,浪费读的性能不是得不偿失么?

哈哈,其实对于这个读操作性能低的问题,Eureka也进行了优化,那就是通过缓存来优化了这个读的性能问题,读的时候先读缓存,缓存没有才会真正调用获取增量的方法来读取增量的信息,所以最后真正走到获取增量信息的方法,请求量很低。

ResponseCacheImpl

ResponseCacheImpl内部封装了缓存的操作,因为不是本文的重点,这里就不讨论了。

总结

所以,通过上面的一步一步分析,终于知道了Eureka读写锁的加锁场景、为什么要加读写锁以及为什么写时加读锁,读时加写锁。这里我再总结一下:

为什么加读写锁

是为了保证获取增量信息的读操作和注册表的写操作互斥,避免由于并发问题导致获取到的增量信息和实际注册表的数据对不上,从而引发客户端的多余的一次全量拉取的操作。

为什么写时加读锁,读时加写锁

其实是为了提升写的性能,而读由于有缓存的原因,真正走到获取增量信息的请求很少,所以读的时候就算加写锁,对于读的性能也没有多大的影响。

从Eureka对于读写锁的使用也可以看出,一个技术什么时候用,如何使用都是根据具体的场景来判断的,不能要一概而论。

M1安装homebrew报错LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54解决方法 在mac系统中,使用homebrew可以很方便的管理包。但按照官网的说明执行命令时总是报错原因是这个资源访问有问题,那么我们可以直接使用国内的镜像。给大家推荐一个中国科学技术大学的镜像站点,里面有各种资源https言归正传,开始踩坑。...... 阅读详情

相关推荐

8.5/Q1,Charls最新高分文章解读!

8 257名受试者中,672人(8.14%)在9年内发生过卒中。在调整的多因素cox回归模型中,TyG和ABSI仍然是卒中的预测因素,TyG的HR为1.25(95%CI:1.06~1.47),ABSI的HR为1.33(95%CI:1.06~1.68)。TyG和ABSI联合诊断效能最高(AUC:0.579,95%CI:0.553~0.597),而TyG(AUC:0.566,95%CI:0.544~0.587)和ABSI(AUC:0.533,95%CI:0.524~0.597)的诊断效能最低。

gsky_sci的博客 1017

读写锁加锁、解锁过程

读写锁加锁、解锁过程读写锁的简单使用源码解析写锁写锁加锁写锁解锁读锁读锁加锁读锁解锁 在进行读写锁源码分析时,必须有AQS(ReentrantLock等)的基础 链接: ReentrantLock加锁和解锁的过程. 读写锁的简单使用 加了读锁,其他线程和本线程写锁阻塞,其他线程写锁不影响(读读可以,读写不行) 加了写锁,本线程写锁不影响(锁重入,次数不能超过最大值65535), package cn.itcast.n8; import lombok.extern.slf4j.Slf4j; import

txm的博客 1721

从STM32F411到华大HC32F460:一个真实项目移植的踩坑与填坑全记录

本文详细记录了从STM32F411移植到华大HC32F460芯片的全过程,包括开发环境搭建、时钟树配置、中断处理、外设驱动、看门狗陷阱、Flash操作和低功耗设计等关键坑点及解决方案。特别针对HC32F460的200MHz主频、双PLL架构和HSRUN模式等特性进行了深入分析,为工程师提供实用的移植指南,帮助节省大量调试时间。

weixin_33691817的博客 421

读锁有什么用?读为什么要加锁?

读为什么要加锁? 1、有些同学认为读锁没有用,他们的理由是:读操作又不会修改数据,想读就读呗,无论读的是就值还是新值,反正能读到。 2、也有同学认为读锁是为了防止多线程读到的数据不一致。 我认为不是这个原因,只需要问两个问题就知道了,首先问不一致的是什么?然后反问不一致会导致什么问题呢? 有些同学认为不一致就是有些线程读的是旧值,有些读的是新值,所以不一致。但是反问导致什么问题,就不是很好回答了,可能回答说为了保险吧,哈哈哈。 实际上即使加读锁,还是会存在有的线程读旧值,有的线程读新值,甚至非公平

weixin_37990128的博客 4386

AI Pika 生成进击的巨人动漫分镜案例

AI Pika 生成进击的巨人动漫分镜案例 Pika 是一个使用AI生成和编辑视频的平台。

独立开发,substack顶级编辑 2576

从FPGA/ASIC工程师视角看DDR:手把手拆解Memory Controller、PHY与DRAM芯片的协作流程

本文从FPGA/ASIC工程师视角深入解析DDR内存子系统,详细拆解Memory Controller、PHY与DRAM芯片的协作流程。通过系统架构分解、接口标准解析和实战调试技巧,帮助工程师优化DDR性能并解决常见问题,涵盖地址映射、命令调度、时序校准等关键技术要点。

weixin_42548888的博客 458

mysql 加写锁_MySQL中的读锁和写锁

在数据库的锁机制中介绍过,数据的锁主要用来保证数据的一致性的,数据库的锁从锁定的粒度上可以分为表级锁、行级锁和页级锁。在我的博客中重点介绍过MySQL数据库的行级锁。这篇文章主要来介绍一下MySQL数据库中的表级锁。本文提到的读锁和写锁都是MySQL数据库的MyISAM引擎支持的表锁的。而对于行级锁的共享读锁和互斥写锁请阅读MySQL中的共享锁与排他锁。我习惯在描述表锁的时候按照读写来区分,在表述...

weixin_30558777的博客 2329

VS2022 中 std::mutex 静态初始化陷阱:一次诡异崩溃的排查记录

VS2022中使用std::mutex时遇到的静态初始化陷阱问题。该问题源于VS2022 17.4版本为std::mutex添加constexpr支持后,全局静态初始化可能导致系统资源未就绪时锁失效或崩溃。文章分析了问题现象、影响范围,并提供了解决方案。最后给出了排查清单和核心建议

qq_34552942的博客 953

MySQL锁--01---读锁、写锁、表锁及案例

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言 前言 https://blog.youkuaiyun.com/u012184539/article/details/88561195?

时光里的博客 1100

用limma包进行多组差异表达分析

写在前面:最近在使用limma包进行差异表达分析,参考了网上许多教程都觉得说的云里雾里,很不清楚。经过我自己一段时间非常痛苦的钻研,弄明白了,解决了我的实际需求。于是决定将我的分析经验写下来,分享给需要的人。 首先加载前期预处理好的表达矩阵。(我的原始表达矩阵文件已附在文后,大家有需要可以下载实践) setwd("E://Rworkplace") data<-read.table...

weixin_40640700的博客 4万+

STM8S全解析之系列文章4---STM8S芯片项目升级引导程序(使用中断接收升级数据)

STM8S全解析之系列文章4—STM8S芯片项目升级引导程序(使用中断接收升级数据) 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 文章目录STM8S全解析之系列文章4---STM8S芯片项目升级引导程序(使用中断接收升级数据)前言一、Flash划分boot和App二、使用步骤1.引入库2.读入数据总结 前言 用过STM8S都知道它没有中断向量重定向,也就意味着STM8S的中断向量没办法指向其他的位置,间接说明升级的引导

weixin_39853312的博客 1032

文件锁(二)——文件锁的读锁和写锁

文件锁的读锁和写锁 对文件加锁时可以加两种锁,分别是“读文件锁”和“写文件锁”,简称读锁和写锁。 读锁、写锁之间关系 读锁和读锁共享:可以重复加读锁,别人加了读锁在没有解锁之前,我依然可以加读锁,这就是共享。 读锁和写锁互斥:别人加了读锁没解锁前,加写锁会失败,反过来也是如此。 加锁失败后两种处理方式: 阻塞,直到别人解锁然后加锁成功为止。 出错返回,不阻塞 写锁与写锁互斥:别人加了写锁在没有解锁前,不能加写锁,加写锁会失败。 加锁失败后两种处理方式: 阻塞,直

Scroll_C的博客 8901

2021秋招IC验证面经-ARM中国/中科芯/飞腾/地平线/中兴

中科芯 (央企福利待遇好,但是百分百不解决户口,适合当地人进去躺平。) 现场面试,三个面试官,时间大约40min 首先介绍一下自己,介绍一下项目。所做项目用到了FIFO吗,深度是多少,位宽是多少,仲裁算法是什么? 验证环境中的reference model是自己写的还是本身就有的,仲裁怎么在参考模型中实现,参考模型怎么获取寄存器的值? 怎么配置RTL寄存器,通过平台的寄存器模型进行寄存器配置,寄存器模型里边的方法,写一个寄存器或读一个寄存器怎么实现? 寄存器如何实现前门访问和后门访问,后门访问时

weixin_48014653的博客 6320

Eureka读时加写锁,写时加读锁,到底是故意为之还是一个bug?

所以,通过上面的一步一步分析,终于知道了Eureka读写锁的加锁场景、为什么要加读写锁以及为什么写时加读锁,读时加写锁。为什么加读写锁是为了保证获取增量信息的读操作和注册表的写操作互斥,避免由于并发问题导致获取到的增量信息和实际注册表的数据对不上,从而引发客户端的多余的一次全量拉取的操作。为什么写时加读锁,读时加写锁其实是为了提升写的性能,而读由于有缓存的原因,真正走到获取增量信息的请求很少,所以读的时候就算加写锁,对于读的性能也没有多大的影响。

jcc4261的博客 539

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Eureka源码13-EurekaServer扩展(读写锁)

因为续约操作是一个发生频率非常高的写操作,若为其添加了写锁,则意味着其它client的续约 处理无法实现并行,发生排队等待。在上述所有方法中,对registry的所有操作中 均没有添加写锁,所以这里的写操作也无需添加读锁。不过,该方式会导致读操作效率的低 下,因为读操作无法实现并行读取,只能排队读取。的数据结构是线程安全的,所以不用加写锁,但是加读锁和为了配合拉取增量注册表的读场景,保证对。队列,写的场景很多,读的场景只有拉取增量注册表。写操作时无法读操作,读操作时不能写操作,保证拉取增量注册表时获取的。

BASK2312的博客 250

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

eureka 读写锁的一点思考

eureka

kznsbs的博客 487

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

图文详述Eureka的缓存机制/三级缓存

一、三级缓存概要 1、三级缓存分别是什么? 一级缓存(注册表)ConcurrentHashMap 二级缓存(ReadWriteMap)guava#LoadingCache 三级缓存(ReadOnlyMap)ConcurrentHashMap 注册一个服务实例 向注册表中写入服务实例信息,并使得二级缓存失效 寻找一个服务 从三级缓存中找,如果有则返回,如果没有则去二级缓存拿并更新,如果二级缓存已经失效,触发guava的回调函数从注册表中同步。 数据同步定时器 每 30s 从二级缓存向三级缓存同步数据 二级缓存

健身变秃,coding变强 9608

Eureka 源码解析 —— Eureka源码解析 —— 应用实例注册发现 (九)之读写锁

1. 概述 本文主要分享Eureka 注册中心的那把读写锁,让我瘙痒难耐,却不得其解。在某次意外的抠脚的一刻( 笔者不抽烟,如果抽烟的话,此处应该就不是抠脚了 ),突然顿悟,爽,这好比... 比喻有点猥琐,笔者就省略 100 字。 不瞎比比,上代码: public abstract class AbstractInstanceRegistry implements InstanceRegistry { private final ReentrantReadWriteLock readWr.

weixin_42073629的博客 470

Eureka中读写锁的奇思妙想,学废了吗?

前言 很抱歉 好久没有更新文章了,公最近的一篇原创还是在去年十月份,这个号确实荒废了好久,感激那些没有把我取消关注的小伙伴。 有读者朋友经常私信问我: ”你号卖了?“ ”文章咋不更新了?“ 不更新主要的原因就是自己太懒了,也不知道要写些什么东西。最近一年还是在零散的学些东西,每次准备提笔写文章都半途而废了,到了最后就干脆不写了。 废话不多说了,还是看文章吧,分享的内容是我自己思考的一些东西,并没有标准答案,希望大家看的时候都能够有自己的见解,有问题可以第一时间联系到我 一起探讨。 跟着我,要么学会,要么学

一枝花算不算浪漫的专栏 549

什么是Eureka?Eureka能干什么?Eureka怎么用?

Spring Cloud 封装了 公司开发的 Eureka 模块来实现服务治理服务治理就是提供了微服务架构中各微服务实例的快速上线或下线且保持各服务能正常通信的能力的方案总称。服务治理的优点: 是 开源微服务框架中一系列项目中的一个。对其进行了二次封装,形成了 子项目,但未对微服务实现原理进行更改,只是进行了化,使开发者更容易使用和整合。在中,对于服务治理有如下3个概念:Eureka Server提供注册服务功能 EurekaClient通过注册中心进行访问 1.4、 什么场景使用Eureka 准确来说是

怪咖@的博客 2万+

来了来了:程序员一定要学废的Eureka中读写锁的使用技巧

本文要学废什么? 本文只想唠唠EurekaServer中关于读写锁的一些使用小技巧。 对于我们正常逻辑思维来说,读锁就是在读的时候加锁,写锁就是在写的时候加锁,这似乎没有什么技巧? 好像什么也学不会了?Oh No ~~~ 读写锁只是通俗的叫法,为何限定读锁只能加在读操作,写锁只能加在写操作呢? 细细品下方面那句话,接下来一起看看网飞的程序员是怎么玩的吧。 读写锁回顾 JDK中常说的读写锁是ReentrantReadWriteLock,我们平时工作中使用ReentrantLock会多一些,这两

Java圈全能架构师的博客 552

真的是神坑啊,Eureka服务无法注册的问题

真的是神坑啊,Eureka服务无法注册的问题问题描述 问题描述 开发微服务的时候用Eureka作为注册中心,在本地的idea中开开心心的测试完没有遇到问题。 于是我便把eureka服务部署到Linux服务器上,这时我启动本地的服务向服务器上的eureka服务注册时,问题出现了。 2019-06-18 10:20:49.916 INFO [myserver,,,] 8028 --- [ ...

weixin_43334641的博客 6528
上一篇: Project Reactor源码分析-subscribeOn
下一篇: 一文学会Spring JDBC 使用
java小姜在线冲
博客等级 码龄4年 53粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值