读写锁的简单介绍

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

        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();
} }

    

最新文章

  1. A library of generic data structures
  2. XidianOJ 1057 卡尔的技能
  3. 无鼠标Windows操作
  4. SpringBoot项目部署与服务配置
  5. Saltstack系列3:Saltstack常用模块及API
  6. 高效 jquery 的奥秘
  7. java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
  8. 单击Android设备后退键,主屏幕键以及旋转屏幕如何影响Activity的生命周期
  9. 源代码管理工具-GIT
  10. Ubuntu 制作U盘启动盘
  11. 【python学习笔记】10.充电时刻
  12. [Leetcode]450. Delete Node in a BST
  13. Lintcode - 20.骰子求和
  14. windows下vmware配置nat网络
  15. web-msg-send 学习 http://www.workerman.net/web-sender
  16. 《A.I.爱》王力宏与人工智能谈恋爱 邀李开复来客串
  17. [剑指Offer]5.二维数组中的查找
  18. Java设计模式(一)普通工场模式 抽象工场模式
  19. select函数用法详解
  20. suiyi

热门文章

  1. vector自实现(一)
  2. 获取URL中的某段字符
  3. 『无为则无心』Python函数 — 35、Python中的闭包
  4. 平滑增加Nginx模块
  5. mysql加强(4)~多表查询
  6. python07day
  7. tcp|ip nagle算法
  8. eureka的简单介绍,eureka单节点版的实现?eureka的自我保护?eureka的AP性,和CP性?
  9. Heartbeat部署
  10. Log4j2日志技术总结