Java 多线程中读写锁 ReadWriteLock 的使用
该博客转载自 lavimer 的 Java 多线程中读写锁 ReadWriteLock 的使用
1. 概念
读写锁分为读锁和写锁,多个读锁之间是不需要互斥的(读操作不会改变数据,如果上了锁,反而会影响效率),写锁和写锁之间需要互斥,也就是说,如果只是读数据,就可以多个线程同时读,但是如果你要写数据,就必须互斥,使得同一时刻只有一个线程在操作。
2. 案例
2.1 三线程读数据,三线程写数据
package com.tao.leanrn.thread.lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @ClassName ReadWrite * @Descriiption 读写锁 * @Author yanjiantao * @Date 2019/8/21 10:42 **/ public class ReadWrite { /** * 共享数据 */ private int data = 0; /** * 读写锁 */ private ReadWriteLock lock = new ReentrantReadWriteLock(); public void get() { // 上读锁 lock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + "----->读锁开始执行..."); Thread.sleep((long)(Math.random() * 10)); System.out.println(Thread.currentThread().getName() + "----->读锁得到数据data=" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放锁 lock.readLock().unlock(); } } public void set() { // 上写锁 lock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + "----->写锁开始执行..."); Thread.sleep((long)(Math.random() * 10)); data++; System.out.println(Thread.currentThread().getName() + "----->写锁得到数据data=" + data); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放写锁 lock.writeLock().unlock(); } } } /** * 测试类 */ class Main{ public static void main(String[] args) { ReadWrite readWrite = new ReadWrite(); // 创建100个读写线程 for (int i = 0; i < 100; i++) { new Thread(() -> { readWrite.get(); }).start(); new Thread(() -> { readWrite.set(); }).start(); } } }
程序运行结果
2.2 模拟 Hibernate 缓存
public class HibernateCache { /* 定义一个Map来模拟缓存 */ private Map<String, Object> cache = new HashMap<String, Object>(); /* 创建一个读写锁 */ private ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** * 模拟Hibernate缓存 * @param key * @return */ private Object getData(String key) { /* 上读锁 */ rwLock.readLock().lock(); /* 定义从缓存中读取的对象 */ Object value = null; try { /* 从缓存中读取数据 */ value = cache.get(key); if (value == null) { /* 如果缓存中没有数据,我们就把读锁关闭,直接上写锁【让一个线程去数据库中取数据】 */ rwLock.readLock().unlock(); /* 上写锁 */ rwLock.writeLock().lock(); try { /* 上了写锁之后再判断一次【我们只让一个线程去数据库中取值即可,当第二个线程过来的时候,发现value不为空了就去缓存中取值】 */ if (value == null) { /* 模拟去数据库中取值 */ value = "hello"; } } finally { /* 写完之后把写锁关闭 */ rwLock.writeLock().unlock(); } /* 缓存中已经有了数据,我们再把已经 关闭的读锁打开 */ rwLock.readLock().lock(); } } finally { /* 最后把读锁也关闭 */ rwLock.readLock().unlock(); } return value; } }
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于