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

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

  • 相关阅读:
    python之Lambda
    oracle数据处理之expdb/impdb
    oracle之dblink
    oracle数据处理之sql*loader(二)
    exsi主机之间使用scp拷贝文件超时问题
    exsi从磁盘中加载虚拟机
    exsi的虚拟机加载U盘
    python 中的property
    hp服务器安装exsi5.5
    关于vsphere的 许可证配置问题
  • 原文地址:https://www.cnblogs.com/mkl34367803/p/14684485.html
Copyright © 2020-2023  润新知