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

    • 读优先
    • 写优先
    • 读写公平
  • 相关阅读:
    Essential C++ 3.1 节的代码练习——哨兵方式
    Essential C++ 3.1 节的代码练习——指针方式
    《搞不定人,你如何带团队?》读书记录
    selenium+python,解决selenium弹出新页面,无法定位元素的问题(报错:Unable to locate element:元素)
    selenium 元素(class_name、link_text、css_selector)定位方法
    selenium+python+eclipse 实现 “问卷星”网站,登录与检查登录示例!
    selenium IDE中log的保存与查看方法
    selenium IDE工具页面介绍!
    selenium IDE 使用方法整理
    selenium IDE的3种下载安装方式
  • 原文地址:https://www.cnblogs.com/xhj928675426/p/13537538.html
Copyright © 2011-2022 走看看