zoukankan      html  css  js  c++  java
  • ThreadLocal不安全的情况举例(附代码)

    ThreadLocal通过Thread.threadlocals保存ThreadLocal的副本,但是ThreadLocal变量在多线程情况下仍然是不安全的。

    class MyClass{
        private Integer value;
        public MyClass(){
        }
        public MyClass(Integer value){
            this.value=value;
        }
    
        public Integer getValue() {
            return value;
        }
    
        public void setValue(Integer value) {
            this.value = value;
        }
    
        @Override
        public String toString() {
            return "MyClass{" +
                    "value=" + value +
                    '}';
        }
    }
    public class ThreadLocalTest {
        static ThreadLocal<MyClass> threadLocal=new ThreadLocal<>();
    
        public static void main(String[] args) {
            MyClass myClass=new MyClass();
            new Thread(){
                @Override
                public void run() {
                    myClass.setValue(10);
                    threadLocal.set(myClass);
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    myClass.setValue(10); //这个值会影响下面线程最后一次打印
                }
            }.start();
    
    
            new Thread(){
                @Override
                public void run() {
                    myClass.setValue(20);
                    threadLocal.set(myClass);
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
    
                }
            }.start();
        }
    }

    通过查看上面代码的执行结果,可以看到,两个线程对myClass的value设置后,相互影响,线程逻辑完全混乱了,并不是我们想象中的各自拥有变量副本。

    正确的写法是多线程共享ThreadLocal变量,但是不共享ThreadLocal里面的变量。也就是每个线程共享Thread.threadLocals的key,而不不共享Thread.threadLocals的value。

    public class ThreadLocalTest111 {
        static ThreadLocal<MyClass> threadLocal=new ThreadLocal<>();
    
        public static void main(String[] args) {
            new Thread(){
                @Override
                public void run() {
                    MyClass myClass=new MyClass(10);
                    threadLocal.set(myClass);
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    myClass.setValue(10); //这个值会影响下面线程最后一次打印
                }
            }.start();
    
    
            new Thread(){
                @Override
                public void run() {
                    MyClass myClass=new MyClass(20);
                    threadLocal.set(myClass);
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(currentThread().getName()+":"+threadLocal.get());
    
                }
            }.start();
        }
    }

    上面这个代码就是线程安全了。

  • 相关阅读:
    centos7.6进行软raid5制作
    面试题 PHP1
    基于githooks利用PHP_CodeSniffer做PSR2代码风格规范检测
    【GC 分代收集算法 VS 分区收集算法】
    【 Redis五大数据类型实现原理】
    【Java反射】
    【GC 垃圾收集器】
    【Redis过期策略/内存淘汰机制/对过期Key的处理】
    【Redis底层数据结构】
    【当骗子遇上研发工程师,还没开始就已经结束】
  • 原文地址:https://www.cnblogs.com/mkl34367803/p/14684485.html
Copyright © 2011-2022 走看看