zoukankan      html  css  js  c++  java
  • ReentrantReadWriteLock可重入读写锁改造HashMap的简单使用

    先改造

    package com.study.framework.annotation;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @Description: 自定义,线程安全的 map ,用读写锁改造HashMap
     * @Auther: BacHe
     * @Date: 2019/9/19 09:46
     */
    public class SafeMap {
        //非线程安全的map
        private static Map<String, Object> map = new HashMap<>();
        //可重入读写锁
        private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        //读锁
        private static Lock r = lock.readLock();
        //写锁
        private static Lock w = lock.writeLock();
    
        //获取一个key 对应的值
        public static final Object get(String key) {
            //加 读锁
            r.lock();
            Object obj = null;
            try {
                obj = map.get(key);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                r.unlock();
            }
            return obj;
        }
    
        //设置 key 对应的value
        public static final Object put(String key, Object value) {
            //加 写锁
            w.lock();
            Object obj = null;
            try {
                obj = map.put(key, value);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                w.unlock();
            }
            return obj;
        }
    
        //清空所有的内容
        public static final void clear() {
            //加 写锁
            w.lock();
            try {
                map.clear();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁
                w.unlock();
            }
        }
    
    }

    测试一下是不是线程安全

    package com.study.framework;
    
    import com.study.framework.annotation.SafeMap;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @Description:
     * @Auther: BacHe
     * @Date: 2019/9/19 10:09
     */
    public class SafeMapTest {
        public static void main(String[] args) {
            //定义原子变量
            AtomicInteger integer = new AtomicInteger(0);
            //定义写入线程
            for (int i = 0; i < 1; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                Thread.sleep(1200);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            int andAdd = integer.getAndAdd(1);
                            Object a = SafeMap.put("a", String.valueOf(andAdd));
                            if (null == a) {
                                a = "null";
                            }
                            System.out.println(Thread.currentThread().getName() + ",---上一个值:" + a.toString()
                                    +",---put入:" + String.valueOf(andAdd));
                        }
                    }
                },"写线程:"+String.valueOf(i+1)).start();
    
            }
            //定义读取线程
            for (int i = 0; i < 3; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            Object a = SafeMap.get("a");
                            if (null != a) {
                                System.out.println(Thread.currentThread().getName() + ",----" + a.toString());
                            } else {
                                System.out.println(Thread.currentThread().getName() + ",----null");
                            }
                        }
    
                    }
                }, "读线程:" + String.valueOf(i + 1)).start();
            }
        }
    }

    观察输出结果,确实是读的时候不会写,写的时候不会读。避免出现脏读现象。

    读线程:1,----null
    读线程:2,----null
    读线程:3,----null
    读线程:3,----null
    读线程:2,----null
    读线程:1,----null
    写线程:1,---上一个值:null,---put入:0
    读线程:1,----0
    读线程:2,----0
    读线程:3,----0
    读线程:2,----0
    读线程:1,----0
    读线程:3,----0
    写线程:1,---上一个值:0,---put入:1
    读线程:3,----1
    读线程:2,----1
    读线程:1,----1
    读线程:3,----1
    读线程:1,----1
    读线程:2,----1
    读线程:1,----1
    读线程:2,----1
    读线程:3,----1
    写线程:1,---上一个值:1,---put入:2
    读线程:1,----2
    读线程:3,----2
    读线程:2,----2
    读线程:1,----2
    读线程:2,----2
    读线程:3,----2
    写线程:1,---上一个值:2,---put入:3
    读线程:2,----3
    读线程:1,----3
    读线程:3,----3
    读线程:3,----3
    读线程:1,----3
    读线程:2,----3
    写线程:1,---上一个值:3,---put入:4
    读线程:1,----4
    读线程:3,----4
    读线程:2,----4
    读线程:3,----4
    读线程:2,----4
    读线程:1,----4
    读线程:1,----4
    读线程:3,----4
    读线程:2,----4
    写线程:1,---上一个值:4,---put入:5
    读线程:2,----5
    读线程:3,----5
    读线程:1,----5
    

    嗯,就是这样。
    虽然用读写锁,改造了hashmap ,但是这是任何的key都会加上读写锁,控制上还是不够精细,可以优化成相同的key 才会有竞争关系,有竞争关系才需要加读写锁。
    更精细的控制就能让性能再提高一个层次。

  • 相关阅读:
    4.22课堂
    4.21课堂
    4.20作业
    4.20课堂
    4.17课堂
    4.16课堂
    4.15作业
    4.15反射与内置方法
    4.10绑定与非绑定
    70、django中间件
  • 原文地址:https://www.cnblogs.com/itbac/p/11548353.html
Copyright © 2011-2022 走看看