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

    • 读优先
    • 写优先
    • 读写公平
  • 相关阅读:
    May 1 2017 Week 18 Monday
    April 30 2017 Week 18 Sunday
    April 29 2017 Week 17 Saturday
    April 28 2017 Week 17 Friday
    April 27 2017 Week 17 Thursday
    April 26 2017 Week 17 Wednesday
    【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式
    April 25 2017 Week 17 Tuesday
    April 24 2017 Week 17 Monday
    为什么丑陋的UI界面却能创造良好的用户体验?
  • 原文地址:https://www.cnblogs.com/xhj928675426/p/13537538.html
Copyright © 2011-2022 走看看