JUC-ThreadLocal


前言

多线程访问同一个共享变量的时候也别容易出现并发问题,特别是在多线程需要对一个共享变量进行写入的时候。为了保证线程的安全,一般使用者在访问共享变量的时候需要进行适当的同步。如下图所示
同步的措施一般是加锁,但是加锁显然加重了使用者的负担。那么有没有一种方式可以做到,当创建一个线程过后,每个线程对其访问的时候,访问的是自己线程的变量呢?其实ThreadLocal就可以做出这样一件事。

ThreadLocal

ThreadLocal是JDK提供的,它提供了线程本地变量,也就是说如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地副本。当多个线程操作这个变量的时候,实际上操作的是自己本地内存里面的变量,从而避免了线程安全问题。创建一个ThreadLocal变量后,每个线程都会复制一个变量到自己的本地内存,如下图所示:

ThreadLocal测试

代码如下:

public class ThreadLocalTest {
static void print(String str){
    System.out.println(str+":"+localVariable.get());
    localVariable.remove();
}
    static ThreadLocal<String> localVariable=new ThreadLocal<String>();

    public static void main(String[] args) throws Exception{

        Thread threadone=new Thread(() -> {
          localVariable.set("threadone local variable");
            print("threadone");
            System.out.println("threadone remove after"+":"+localVariable.get());
        });

        Thread threadtwo=new Thread(() -> {
            localVariable.set("threadtwo local variable");
            print("threadtwo");
            System.out.println("threadtwo remove after"+":"+localVariable.get());
        });

        threadone.start();
        threadtwo.start();

    }

}

结果:

ThreadLocal类结构

ThreadLocal不支持继承性

看一个栗子:

public class ThreadLocaltest2 {
public  static  ThreadLocal<String> threadLocal=new ThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("hello world");
        Thread thread=new Thread(() -> {
            System.out.println("thread:"+threadLocal.get());
        });
        thread.start();


        System.out.println("main:"+threadLocal.get());
    }
}

输出结果:

threadlocal变量是在main父线程中声明的,因此子线程thread是获取不到的。

InheritableThreadLocal

为了解决上诉问题,InheritableThreadLocal应运而生。

public class InheritableThreadLocalTest {
    public  static  InheritableThreadLocal<String> threadLocal=new InheritableThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("hello world");
        Thread thread=new Thread(() -> {
            System.out.println("thread:"+threadLocal.get());
        });
        thread.start();


        System.out.println("main:"+threadLocal.get());
    }


}

输出结果:

posted @ 2021-03-01 11:20  西伯利亚爱学习的狼  阅读(103)  评论(0编辑  收藏  举报