AI工具人
提示词工程师

ThreadLocal Java多线程下的影分身之术

如果写过多线程的代码,你肯定考虑过线程安全问题,更进一步你可能还考虑在在线程安全的前提下性能的问题。大多数情况下大家用来解决线程安全问题都会使用同步,比如用synchron或者concurrent包提供的各种锁,当然这些都能解决问题。但有多线程做同步一定会涉及到资源争抢和等待的问题。java中各种同步方法都是提供一种准入机制,JVM会调用系统同步原语来保证临界区任意时刻只能有一个线程进入,那必然其他线程都得等待了,性能的瓶颈就在这同步上了。

  解决问题最好的方式是啥?当然是避免问题的发生了。ThreadLocal就是用这样一种方式提升性能的。ThreadLocal遍历会为每个线程单独维护一份值,某个线程对其做任何操作都不会影响其他的线程,这相当于这个对象在每个线程下面都有了一个分身。ThreadLocal是以Thread为维度实现的,所以多线程之间也不会有争抢和等待,从而避免同步变成瓶颈,下文我们会从源码的维度去看这些都是如何实现的。
  ThreadLocal也不是万金油,它也只能在多线程之间数据相互独立的情况下使用,如果是多线程间的数据同步,还得使用某个同步的方式。 我的理解,ThreadLocal是在临时变量完全不共享和全部变量完全共享之间取了个折中,在多线程数据一致的情况下完美的避免了资源争抢和等待,提高了性能。
  

如何使用

  ThreadLocal的使用也很简单,直接new ThreadLocal<T>(); 就可以了,然后可以通过set()和get()分别设值和获取值。以下代码展示我如果使用ThreadLocal<Integer>如何为每个线程单独维护一个值的,而且线程之间也不会相互干扰。

public class Demo extends Thread {
    private static ThreadLocal<Integer> counter = new ThreadLocal<>();

    @Override
    public void run() {
        counter.set(ThreadLocalRandom.current().nextInt(100));
        System.out.println(Thread.currentThread().getName() + ":" + counter.get());
        try {
            Thread.sleep(2000 + ThreadLocalRandom.current().nextInt(3000));
        } catch (Exception e) {
            e.printStackTrace();
        }
        counter.set(counter.get()+100);
        System.out.println(Thread.currentThread().getName() + ":" + counter.get());
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Demo();
            thread.setName("Thread" + i);
            thread.start();
        }
    }
}

  上面我用到了ThreadLocal的set和get方法,其运行结果如下,因为使用了随机数,可能每次运行解决会不一致。可以很明显看得出,虽然多线对统一个Object操作,但却没有影响到各自的值。

赞(0) 打赏
未经允许不得转载:XINDOO » ThreadLocal Java多线程下的影分身之术
描述文字

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫