读写锁其实就是将一个锁拆分为读锁和写锁两个锁,然后加锁的时候可以加读锁也可以加写锁
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // 读锁 lock.readLock().lock(); lock.readLock().unlock(); // 写锁 lock.writeLock().lock(); lock.writeLock().unlock();
如果有一个线程加了写锁,其他线程就不能加写锁,因为同一时间只允许一个线程加写锁,加了写锁说明要写一个共享数据,这个时候不能让其他线程来写这个数据
如果有线程加了写锁,其他线程就不能加读锁,因为有人要写入数据,如果其他人来读取,读取的数据会跟预想不一样,所以加上写锁,其他线程就不能读取
如果一个线程加了读锁,其他线程可以随意加读锁,因为不涉及到数据变动,但是不能加写锁,既然有人在读数据就不能随意变更数据
二,读写锁优化开始之前需要先了解一下微服务注册中心的基本原理,对微服务注册中心有个大致的概念。
我们一般使用的微服务注册中心一般都是Eureka 或者 Consul 或者自己公司开发的微服务注册中心,无论什么样的服务注册中心,肯定都有一个服务注册表的概念
这个服务注册表就是存放了我们各个服务的地址信息,每个服务多少实例,每个服务实例部署在哪些机器,监听哪些端口
服务注册表如上图,有人写,也会有人读,比如有个服务启动的时候回来注册,这个就是写然后注册完其他的服务需要读取注册表
所以这个注册表天然的就是有读写并发问题,可能会有多个线程写,也可能会有多个线程读。如果对注册表的数据不加任何保护措施,可能发送并发写的情况,这个时候会导致数据错乱
如果对服务注册表的所有数据都加synchornized,这样肯定不合适,因为这样服务注册表全部变成串行化的了 ,性能肯定低。
我们想要的结果是,有人在读数据表的时候其他人都可以随便读,但是不能写入。
在有人要写入注册表的时候,其他人不能写入,也不能读。
其实⼤部分时候都是读操作,所以使⽤读锁可以让⼤量的 线程同时来读数据,不需要阻塞不需要排队,保证⾼并发读的性能是⽐较⾼的。 然后少量的时候是有服务上线要注册数据,写数据的场景是⽐较少的,此时写数据的时候,只 能⼀个⼀个的加写锁然后写数据,同时写数据的时候就不允许别⼈来读数据了。 所以读写锁是⾮常适合这种读多写少的场景的。 另外,我们能不能尽量在写数据的期间还保证可以继续读数据呢?⼤量加读锁的时候,会阻塞 ⼈家写数据加写锁过⻓时间,这种情况能否避免呢? 可以的,采⽤多级缓存的机制



