zoukankan      html  css  js  c++  java
  • JUC----04

    1.1 读写问题

    ReadWriteLockUnsafeDemo:

    public class ReadWriteLockUnsafeDemo {
        // TODO: 2020/7/25  模拟多线程对公共资源类的读和写操作,没有加锁,不安全
        static class Cache {
            private HashMap<String, Object> cache = new HashMap<>();
    
            //写入缓存
            public void put(String key, Object val) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 开始写入");
                    cache.put(key, val);
                    System.out.println(Thread.currentThread().getName() + " 写入完成");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
    
            //从缓存中读取数据
            public void get(String key) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 开始读取");
                    Object obj = cache.get(key);
                    System.out.println(Thread.currentThread().getName() + " 读取完成 : " + obj);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
        }
    
        public static void main(String[] args) {
            Cache cache = new Cache();
            for (int i = 0; i < 5; ++i) {
                final int tempI = i;
                new Thread(() -> {
                    cache.put(String.valueOf(tempI), tempI);
                }).start();
            }
    
            for (int i = 0; i < 5; ++i) {
                final int tempI = i;
                new Thread(() -> {
                    cache.get(String.valueOf(tempI));
                }).start();
            }
        }
    }
    

    运行结果:

    Thread-0 开始写入
    Thread-1 开始写入
    Thread-1 写入完成
    Thread-0 写入完成
    Thread-2 开始写入
    Thread-2 写入完成
    Thread-3 开始写入
    Thread-3 写入完成
    Thread-5 开始读取
    Thread-5 读取完成 : 0
    Thread-4 开始写入
    Thread-4 写入完成
    Thread-6 开始读取
    Thread-6 读取完成 : 1
    Thread-7 开始读取
    Thread-7 读取完成 : 2
    Thread-8 开始读取
    Thread-9 开始读取
    Thread-9 读取完成 : 4
    Thread-8 读取完成 : 3
    

    首先我们可以发现在写操作的时候线程发生的争抢。

    ReadWriteLockDemo:

    public class ReadWriteLockDemo {
        /**
         * * 读-读 : 无锁
         * * 读-写 : 锁
         * * 写-写 : 锁
         */
        //模拟缓存被读和被写
        static class Cache {
            private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    
            private HashMap<String, Object> cache = new HashMap<>();
    
            //写入缓存
            public void put(String key, Object val) {
                /**
                 * 加写锁
                 */
                readWriteLock.writeLock().lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " 开始写入");
                    cache.put(key, val);
                    System.out.println(Thread.currentThread().getName() + " 写入完成");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    readWriteLock.writeLock().unlock();
                }
            }
    
    
            //从缓存中读取数据
            public void get(String key) {
                /**
                 * 加读锁
                 */
                readWriteLock.readLock().lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " 开始读取");
                    Object obj = cache.get(key);
                    System.out.println(Thread.currentThread().getName() + " 读取完成 : " + obj);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    readWriteLock.readLock().unlock();
                }
            }
        }
    
        public static void main(String[] args) {
            Cache cache = new Cache();
            for (int i = 0; i < 5; ++i) {
              final int tempI = i;
                new Thread(() -> {
                    cache.put(String.valueOf(tempI), tempI);
                }).start();
            }
    
            for (int i = 0; i < 5; ++i) {
                final int tempI = i;
                new Thread(() -> {
                    cache.get(String.valueOf(tempI));
                }).start();
            }
        }
    }
    

    运行结果:

    Thread-0 开始写入
    Thread-0 写入完成
    Thread-1 开始写入
    Thread-1 写入完成
    Thread-2 开始写入
    Thread-2 写入完成
    Thread-3 开始写入
    Thread-3 写入完成
    Thread-4 开始写入
    Thread-4 写入完成
    Thread-5 开始读取
    Thread-5 读取完成 : 0
    Thread-6 开始读取
    Thread-6 读取完成 : 1
    Thread-7 开始读取
    Thread-7 读取完成 : 2
    Thread-8 开始读取
    Thread-8 读取完成 : 3
    Thread-9 开始读取
    Thread-9 读取完成 : 4
    

    可以看到写操作保证了原子性,读操作不加锁任意读。
    这里的读操作不加锁,可能有些人会说既然不加锁,那为什么这一步要获取读锁?

    这里的加锁是为了和读操作分离开来,保证上面的读锁释放完后(读操作做完了)再进行读,而各个读线程之间是不加锁的。
    java这部分东西都藏在源码里了,我个人认为上面的代码严格来说属于写优先算法。写写互斥,写优先。
    熟悉操作系统的都知道读写问题一般分三种:

    • 读优先
    • 写优先
    • 读写公平
  • 相关阅读:
    djongo 前端页面展示自定义api返回的列表数据,并拼接到table上
    ou are trying to add a non-nullable field 'address' to person without a default; we can't do that (the database needs something to populate existing rows).
    python string 类型的公钥转换类型并解密
    Django 禁止访问403,CSRF验证失败,相应中断
    springboot async
    此博客可能不再更新,往后博文将发布在 GitHub 中
    css 中 transition 需要注意的问题
    学习笔记(九)
    微信小程序 drawImage 问题
    学习笔记(八)
  • 原文地址:https://www.cnblogs.com/xhj928675426/p/13537538.html
Copyright © 2011-2022 走看看