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这部分东西都藏在源码里了,我个人认为上面的代码严格来说属于写优先算法。写写互斥,写优先。
    熟悉操作系统的都知道读写问题一般分三种:

    • 读优先
    • 写优先
    • 读写公平
  • 相关阅读:
    springmvc常用注解之@Controller和@RequestMapping
    解决nginx负载均衡的session共享问题
    iOS顶部滑动菜单:FDSlideBar 与NinaPagerView
    C#中使用WeiFenLuo.WinFormsUI.Docking.dll实现窗口停靠效果
    [转]C#使用Log4Net记录日志
    ICSharpCode.SharpZipLib 开源压缩库使用示例
    WorldWind源码剖析系列:日志类Log
    [转]反射基础
    WorldWind源码剖析系列:星球球体的加载与渲染
    Vue 前端路由 vue-router
  • 原文地址:https://www.cnblogs.com/xhj928675426/p/13537538.html
Copyright © 2011-2022 走看看