Java并发编程-读写锁,手写一个简单的缓存

文章目录

  • 手写一个缓存
    • 没有加锁之前
    • 加ReentrantLock锁
    • ReentrantReaderWriteLock

手写一个缓存

没有加锁之前


/**
 * 多个线程同时读一个资源类没有任何问题,读取共享资源
 * 小总结
 * 读-读 共享
 * 写-写 互斥
 * 读-写 互斥
 * 

* 写操作:原子+独占,整个过程必须是完整,中间不可被分割和打断 */ class MyCache { //资源类 //volatile保持内存的可见性 private volatile Map<String, Object> map = new HashMap<>(); //private ReentrantLock lock = new ReentrantLock(); //private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); //缓存写入 public void put(String key, Object value) throws InterruptedException { // lock.writeLock().lock(); // try { System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key); TimeUnit.MILLISECONDS.sleep(100); map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 写入完成:"); // } catch (Exception e) { // e.printStackTrace(); // } finally { // lock.writeLock().unlock(); // } } public void get(String key) throws InterruptedException { // lock.readLock().lock(); // try { System.out.println(Thread.currentThread().getName() + "\t 正在读取:"); TimeUnit.MILLISECONDS.sleep(100); Object o = map.get(key); System.out.println(Thread.currentThread().getName() + "\t 去读完成:" + o); // } catch (Exception e) { // e.printStackTrace(); // } finally { // lock.readLock().unlock(); // } } }

调用

public class ReadWriteLockDemo {
     

    public static void main(String[] args) {
     

        MyCache myCache = new MyCache();
        for (int i = 0; i < 5; i++) {
     
            final int temp = i;
            new Thread(() -> {
     
                try {
     
                    myCache.put(temp + "", temp + "");
                } catch (InterruptedException e) {
     
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }

        for (int i = 0; i < 5; i++) {
     
            final int temp = i;
            new Thread(() -> {
     
                try {
     
                    myCache.get(temp + "");
                } catch (InterruptedException e) {
     
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }

    }
}

输出结果:

Java并发编程-读写锁,手写一个简单的缓存_第1张图片
从结果中可以看出,在不加锁的情况下,写操作还没有完成就有读操作去读,结果读出来的全是null。

加ReentrantLock锁

会导致同一时间下只能有一个线程去操纵资源类。也就是说读与读之间也不能共享了

ReentrantReaderWriteLock

其中ReentrantReaderWriteLock有读锁和写锁,在做读操作的时候加上读锁,在做写操作的时候加上写锁。
这样读与读共享,读与写互斥,写与写互斥。


/**
 * 多个线程同时读一个资源类没有任何问题,读取共享资源
 * 小总结
 * 读-读 共享
 * 写-写 互斥
 * 读-写 共享
 * 

* 写操作:原子+独占,整个过程必须是完整,中间不可被分割和打断 */ class MyCache { //资源类 //volatile保持内存的可见性 private volatile Map<String, Object> map = new HashMap<>(); private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); //缓存写入 public void put(String key, Object value) { //开启写锁 lock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key); TimeUnit.MILLISECONDS.sleep(100); map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 写入完成:"); } catch (Exception e) { e.printStackTrace(); } finally { //关闭写锁 lock.writeLock().unlock(); } } public void get(String key) { //开些读锁 lock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + "\t 正在读取:"); TimeUnit.MILLISECONDS.sleep(100); Object o = map.get(key); System.out.println(Thread.currentThread().getName() + "\t 去读完成:" + o); } catch (Exception e) { e.printStackTrace(); } finally { //关闭读锁 lock.readLock().unlock(); } } } public class ReadWriteLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 0; i < 5; i++) { final int temp = i; new Thread(() -> { myCache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); } for (int i = 0; i < 5; i++) { final int temp = i; new Thread(() -> { myCache.get(temp + ""); }, String.valueOf(i)).start(); } } }

结果

Java并发编程-读写锁,手写一个简单的缓存_第2张图片
从结果中可以看出,写与写之间是互斥,写与读之间是互斥的不会相互打断。
而读操作之间是在写完之后去共享完成的

你可能感兴趣的:(Java并发,多线程,java,并发编程)