ThreadLocal 源码解析

了解 ThreadLocal

在多线程中,对于同一个对象的访问和修改会造成冲突,而使用 ThreadLocal 创建的变量只能被当前线程使用,不会受到其他线程的干扰。

例如我们有个计数器,一共有三个线程,我们想让每个线程都从 1 开始计数,然后按顺序 1、2、3、4 递增,这时候用线程同步的话,一种可能的情况是 Thread1-1,Thread2-2,Thread3-3,而我们想要的是 Thread1-1,Thread1-2,Thread1-3,Thread2-1,Thread2-2 这效果。

实现独立计数器

AIncrement.java

class AIncrement {
    int num = 0;
    public int increase() {
        num = num + 1;
        return num;
    }
    public void print() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + " " + increase());
        }
    }
}

ThreadLocalTest.java

class ThreadLocalTest {
    public static void main(String[] args) {
        AIncrement increment = new AIncrement();
        for (int i = 0; i < 3; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    increment.print();
                }
            }).start();
        }
    }
}

控制台打印出:thread_local_a

这显然和我们的预期不一样,因为 num 在多线程共享下,读取-赋值-写入的操作引起了冲突。

下面我们用 ThreadLocal 实现我们想要的。BIncrement.java

class BIncrement {
    ThreadLocal<Integer> num = ThreadLocal.withInitial(() -> 0);
    public int increase() {
        num.set(num.get() + 1);
        return num.get();
    }
    public void print() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + " " + increase());
        }
    }
}

将测试类稍微改写下,然后运行,控制台打印如下:thread_local_b

这个结果就符合我们的需求了。

ThreadLocalMap

这是因为 ThreadLocal 中含有一个静态内部类 ThreadLocalMap,该 Map 的键为当前线程,值为我们需要设置的值,也就是说为每一个线程都存储了一个变量。这样子其实就相当于在单个线程中运行代码,自然不会出现多线程中访问变量冲突的问题。

ThreadLocal.withInitial(() -> 0);

是 JDK1.8 新增的方法,相当于

ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
    @Override
    protected Integer initialValue() {
        return super.initialValue();
    }
};

ThreadLocal API

ThreadLocal 提供的 API 不多,其中 get() 可以获取我们存储的变量值,set() 则是设置变量值,remove() 移除当前线程的变量值,被移除之后,如果再调用 get(),则会获取初始化的值。

想了解更多关于 ThreadLocal 的内容,可以查看 JDK 源码或者搜索相关资料,这里只是自己做个记录,很浅显。

源码:https://juejin.im/entry/58b048b28ac24728d53abadf#comment

https://juejin.im/entry/58cb76681b69e6006b715c1b

https://juejin.im/entry/597ede3bf265da3e185e7de1

https://mp.weixin.qq.com/s/Dsy_fBzrzvbSUtcLuc7ebg

https://mp.weixin.qq.com/s/rZplvCTu31jVX5fwqsGoxg

猜你喜欢

转载自blog.csdn.net/hanjungua8144/article/details/81353928
今日推荐