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();
        }
    }

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

  • 相关阅读:
    前端面试分享
    1
    22
    微信同声传译插件的使用
    微信小程序基于第三方插件微信同声传译,以及一些问题解决办法
    阿里云服务器各种活动集锦
    腾讯云多人直播开发第一天,基于IE游览器的ActiveX开发
    vue组件化学习第三天
    vue组件化学习第二天
    vue组件化学习第一天
  • 原文地址:https://www.cnblogs.com/mkl34367803/p/14684485.html
Copyright © 2011-2022 走看看