Java 您可以选择本地<;原子整数>;可能有用吗?

Java 您可以选择本地<;原子整数>;可能有用吗?,java,multithreading,atomic,Java,Multithreading,Atomic,所以我在一些Java代码中只使用了ThreadLocal。 现在,对于链接代码来说,这显然是无用的,还有其他导致请求被拒绝的问题 而且它似乎总是无用的:AtomicInteger(来自java.util.concurrent.atomic包)是为多线程访问而设计的,而ThreadLocal使每个线程都有自己的值,那么为什么还要使用它呢 我的问题是:在任何情况下,ThreadLocal是否有用?是的,我们可能会提出一个合理的方案: 在每个任务开始时,我们需要一个AtomicInteger的线程本地

所以我在一些Java代码中只使用了
ThreadLocal

现在,对于链接代码来说,这显然是无用的,还有其他导致请求被拒绝的问题

而且它似乎总是无用的:
AtomicInteger
(来自java.util.concurrent.atomic包)是为多线程访问而设计的,而
ThreadLocal
使每个线程都有自己的值,那么为什么还要使用它呢


我的问题是:在任何情况下,
ThreadLocal
是否有用?

是的,我们可能会提出一个合理的方案:

  • 在每个任务开始时,我们需要一个
    AtomicInteger
    的线程本地实例
  • 我们继续将这个对象分布在其他几个线程中,例如由主任务线程分叉的子线程

  • 如果不评估出现这种情况的整个上下文,我们就无法判断。

    假设每个线程需要一个整数计数器。ThreadLocal只能处理对象,因此逻辑上我们需要使用int-wrapper-Integer

    ThreadLocal<Integer> count = new ThreadLocal<>();
    ...
    count.set(count.get() + 1);
    
    ThreadLocal count=new ThreadLocal();
    ...
    count.set(count.get()+1);
    
    另外,我们可以使用AtomicInteger,不是因为它是线程安全的,而是因为它是可变的

    ThreadLocal<AtomicInteger> count = new ThreadLocal<>();
    ...
    count.get().incrementAndGet();
    
    ThreadLocal count=new ThreadLocal();
    ...
    count.get().incrementAndGet();
    

    版本2的性能比版本1要好得多,版本1是一个真正的性能杀手

    我认为对于
    ThreadLocal
    ,只有一些奇怪的原因。在某些情况下,
    ThreadLocal
    不是对
    AtomicInteger
    的唯一引用,因此更多线程可以访问它。当你发现自己处于这种情况下,我认为你最好仔细看看你的设计

    如果您不需要
    AtomicInteger
    的线程安全性,而只需要它的易变性,我更喜欢使用
    int[]
    。与AtomicInteger结合完全控制相比,开销更小:

    ThreadLocal<int[]> count = new ThreadLocal<>();
    ...
    count.set(new int[1]);
    ...
    count.get()[0] = 42;
    ...
    count.get()[0] += 4711;
    
    ThreadLocal count=new ThreadLocal();
    ...
    count.set(新整数[1]);
    ...
    count.get()[0]=42;
    ...
    count.get()[0]+=4711;
    
    这不是一条有趣的评论,但我真的想不出任何评论。我同意你的推理,并认为它排除了ThreadLocal有用的任何情况。除非使用反射,否则无法访问另一个线程的ThreadLocal。1。这是否意味着我们可能需要这样做,因为我们可能需要这样做?2.但在这种情况下,首先使用ThreadLocal是明智的。虽然我同意,如果没有明确的上下文,很难排除问题。@selig如果所有这些都发生在服务器代码中,则每个客户端请求都由其自己的线程单独提供服务,并且主线程启动其自己的线程组并分发
    AtomicInteger
    ,这可能需要从以前的任务中重用(每次都不是一个新的对象)。是的,这是一个延伸,但这并不重要:一旦你有了需要,你就有了它,而且你没有罪。是的,这听起来像是一个合法的场景(多线程服务器,一个线程/客户机交给多个工作人员)如果有更好的答案,我会暂缓接受。这一点很好。我使用AtomicReference将结果对象从可运行代码传递回调用程序-不是因为我需要原子性,而是因为我需要一个可变引用,而且我太懒了,无法为此创建类。所以,仅仅为了有一个编写良好的包装器?也许因此,stdlib应该提供一个可变整数类或其他什么。
    AtomicInteger
    使用了
    volatile
    和一些隐藏的同步。因此,我不清楚在这种情况下,它的开销与
    Integer
    的装箱开销相比如何。您是否检查过“版本1是一个真正的性能杀手”具有正确基准的语句?我使用JMH进行了测试。~~~基准模式Cnt分数错误单位ThreadLocalBenchmark.testAtomicInteger ss 20000 92.736±1.461 us/op ThreadLocalBenchmark.testInteger ss 20000 111.812±2.375 us/op~~~原子整数更快。