读写锁的简单介绍

    所谓的读写锁,就是将一个锁拆分为读锁和写锁两个锁,然后你加锁的时候,可以加读锁,也可以加写锁。

        ReentrantLock lock=new ReentrantLock();
lock.wirteLock.lock();
lock.wirteLock.unlock(); lock.readLock.lock();
lock.readLock.unlock();

    如果有一个现场加了写锁,那其他线程就不能加写锁了,同一时间只允许一个线程加锁,因为加了写锁的就意味着有人要写一个共享数据,那同时就不能让全体人来写这个数据了。

    同时如果有线程加了写锁,其他线程也不能加读锁了,因为既然都有人在写数据了,你其他人当然不能来读数据了。

    如果有一个线程加了读锁,别的线程是可以随意加读锁的,因为只是有线程在读数据,其他线程也可以来读数据。

    同时如果一个线程加了读锁,此时其他线程是不可以加写锁的,因为既然有人在读数据了,就不能随便让你来写数据了。

  微服务注册中心的读写锁优化

    我们知道,微服务的注册中心在内存中,肯定会有一个服务注册表的概念。这个服务注册表存放了各个微服务注册时候发来的自己的地址信息,里面保存了服务有多少个服务实例,每个服务实例部署在哪台机器山监听哪个端口号,主要是这样的信息。

    OK,那现在问题来了,这个服务注册表的数据,有人读,也有人写。

    比如:有的服务器启动的时候回来猪儿,此时要修改服务注册表的数据。这个就是写的过程。

    接着,别的服务也会来读取这个服务注册表的数据,因为每个服务都需要感知其他服务在哪些机器山部署。

    所以这个内存里的服务注册表的数据,天然就是有并发读写问题的,可能会有多个检查来写,也可能会有多个线程来读。

    如果你对同一份注册表的数据,不加任何的保护措施,那可能存在多线程并发修改共享数据的问题,可能导致数据错乱。

    1、可以考虑加synchronized,直接让所有线程对服务注册表的读写操作,全部串行化。

      这种做法,太暴力了,在并发的场景下,性能也不会很高。

    2、使用读写锁。

      一旦有人在写服务器注册表的数据,我们就加一个写锁,此时别人不能写,也不能读。

      一旦有人在读数据,此时可以让别人读,但是不允许别人写。

      这样做的好处是:我们的业务大部分都是读操作,写数据的场景比较少,此时写数据,使用读锁可以让大量线程同时来读数据,不需要阻塞不需要排队,保证高并发的读写性能比较高。

      然后少量的场景,可以加写锁,一个一个写。

      还有一个问题,就是大量加读锁的阻塞,会导致写数据时间过长,这种情况能否避免呢,就是通过多级缓存机制来避免。

      伪代码如下:

public class ServiceRegistry {

    //服务注册表
private Map<String, Map<String,InstanceInfo>> registry=new HashMap<>(); //针对注册表准备的读写锁
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
private ReentrantReadWriteLock.WriteLock writeLock=lock.writeLock();
private ReentrantReadWriteLock.ReadLock readLock=lock.readLock(); public void register(){
writeLock.lock();
//将服务实例信息写入到内存中
writeLock.unlock();
} public Map<String,Map<String, InstanceInfo>> getRegistry(){
readLock.lock();
//返回服务注册表的数据
readLock.unlock();
} }

    

Java中读写锁的介绍的更多相关文章

  1. linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客

    linux中读写锁的rwlock介绍-nk_ysg-ChinaUnix博客 linux中读写锁的rwlock介绍 2013-02-26 13:59:35 分类: C/C++   http://yaro ...

  2. java多线程-读写锁

    Java5 在 java.util.concurrent 包中已经包含了读写锁.尽管如此,我们还是应该了解其实现背后的原理. 读/写锁的 Java 实现(Read / Write Lock Java ...

  3. java多线程-读写锁原理

    Java5 在 java.util.concurrent 包中已经包含了读写锁.尽管如此,我们还是应该了解其实现背后的原理. 读/写锁的 Java 实现(Read / Write Lock Java ...

  4. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

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

    前言 很抱歉 好久没有更新文章了,最近的一篇原创还是在去年十月份,这个号确实荒废了好久,感激那些没有把我取消关注的小伙伴. 有读者朋友经常私信问我: "你号卖了?" "文 ...

  6. 史上最全 Java 中各种锁的介绍

    更多精彩原创内容请关注:JavaInterview,欢迎 star,支持鼓励以下作者,万分感谢. 锁的分类介绍 乐观锁与悲观锁 锁的一种宏观分类是乐观锁与悲观锁.乐观锁与悲观锁并不是特定的指哪个锁(J ...

  7. 利用Java的读写锁实现缓存的设计

    Java中的读写锁: 多个读锁不互斥, 读锁与写锁互斥, 写锁与写锁互斥, 这是由JVM自行控制的,我们只要上好相应的锁即可. 缓存的设计: package com.cn.gbx; import ja ...

  8. java中数据流的简单介绍

    java中的I/O操作主要是基于数据流进行操作的,数据流表示了字符或者字节的流动序列. java.io是数据流操作的主要软件包 java.nio是对块传输进行的支持 数据流基本概念 “流是磁盘或其它外 ...

  9. pthread中读写锁

    读写锁很像一个互斥量,他阻止多个线程同时修改共享数据的另一种方法,区分不同互斥量的是他是分读数据和写数据,一个读写锁允许同时多个线程读数据,只要他们不修改数据. 只要没有写模式下的加锁,任意线程都可以 ...

随机推荐

  1. 推荐召回--基于物品的协同过滤:ItemCF

    目录 1. 前言 2. 原理&计算&改进 3. 总结 1. 前言 说完基于用户的协同过滤后,趁热打铁,我们来说说基于物品的协同过滤:"看了又看","买了又 ...

  2. golang中的标准库反射

    反射 反射是指程序在运行期对程序本身访问和修改的能力 变量的内在机制 变量包含类型信息和值信息 var arr [10]int arr[0] = 10 类型信息:是静态的元信息,是预先定义好的 值信息 ...

  3. 报错org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.mybatis.spring.SqlSessionFactoryBean]

    超级大坑 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.mybati ...

  4. springboot加载外部配置文件

    网上搜集和整理如下(自己已验证过) 1. war包在tomcat中加载外部配置文件 war包运行在独立tomcat下时,如何加载war包外部配置application.properties,以达到每次 ...

  5. python——rsa加签名以及分段加密

    借鉴 https://www.cnblogs.com/sammy1989/p/9583965.html 最近请求一个系统,对方要求加密.折腾了一天,使用pycryptodome库,最终代码如下: #! ...

  6. 微信小程序音频播放 InnerAudioContext 的用法

    今天项目上涉及到了微信小程序播放音频功能,所以今天跟着一些教程做了个简单的播放器 1.实现思路 刚开始想着有没有现成的组件可以直接用,找到了微信的媒体组件 audio,奈何看着 1.6.0版本开始,该 ...

  7. VUE项目部署到线上生产环境,Loading chunk xxx failed

    项目部署到生产环境,路由点击无效,报错 Loading chunk chunk-xxxxx failed.(missing xxxx) 加载失败,错误的路径. 话不多说,直接贴代码: vue.conf ...

  8. Pytest用例编写1

      一.编写pytest测试样例非常简单,只需要按照下面的规则: 测试文件以test_开头(以_test结尾也可以) 测试类以Test开头,并且不能带有 __init__ 方法 测试函数以test_开 ...

  9. Spring系列12: `@Value` `@Resource` `@PostConstruct` `@PreDestroy` 详解

    本文内容 @Resource实现依赖注入 @Value详细使用 @PostConstruct @PreDestroy的使用 @Resource实现依赖注入 前面章节介绍了使用@Autowired注入依 ...

  10. c++ 子类与父类之间的类型转换

    子类与父类之间的类型转换 先给一段代码 class Base { public: int a = 10; }; class pub_Derv : public Base { Base *getBase ...