【问题标题】:Could ThreadLocal<AtomicInteger> possibly be useful?ThreadLocal<AtomicInteger> 可能有用吗?
【发布时间】:2013-06-05 07:13:21
【问题描述】:

所以我在一些 Java 代码中只是 saw someone try to useThreadLocal&lt;AtomicInteger&gt;
现在,对于链接代码,这显然是无用的,以及导致请求被拒绝的其他问题。

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

我的问题是:在任何情况下ThreadLocal&lt;AtomicInteger&gt; 会有用吗?

【问题讨论】:

  • 不是一个有趣的评论——但我真的想不出任何评论。我同意您的推理,并认为它排除了任何 ThreadLocal 有用的情况。
  • 除非使用反射,否则无法访问另一个线程的threadlocal。

标签: java multithreading atomic


【解决方案1】:

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

  1. 我们需要在每个任务开始时使用AtomicInteger 的线程本地实例;
  2. 我们继续将此对象分配给其他几个线程,例如由主任务线程分叉的子线程。

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

【讨论】:

  • 1.这是否是说我们可能需要这样做,因为我们可能需要这样做? 2. 但是在这种情况下,使用 ThreadLocal 开始是明智的。虽然我同意,如果没有明确的背景,很难排除这种可能性。
  • @selig 如果这一切都发生在服务器代码中,每个客户端请求都由其自己的独立线程提供服务,并且该主线程启动自己的线程组并分发AtomicInteger,这可能需要从以前的任务中重用(它不是每次都是新对象)。是的,这有点牵强,但这并不重要:一旦你有需要,你就有了,而且你不会为此感到内疚。
  • 是的,这听起来像是一个合法的场景(多线程服务器,一个线程/客户端移交给多个工作人员)。如果有更好的答案出现,我会暂缓接受。
【解决方案2】:

假设我们每个线程都需要一个整数计数器。 ThreadLocal 只能处理对象,所以逻辑上我们需要使用 int 包装器 - 整数

ThreadLocal<Integer> count = new ThreadLocal<>();
...
count.set(count.get() + 1);

我们也可以使用 AtomicInteger,不是因为它是线程安全的,而是因为它是可变的

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

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

【讨论】:

  • 好点。我使用 AtomicReference 将结果对象从 Runnable 中的代码传递回调用程序 - 不是因为我需要原子性,而是因为我需要一个可变引用并且我懒得为此创建一个类。跨度>
  • 所以只是为了拥有一个编写良好的包装器?那么,也许标准库应该提供一个 MutableInteger 类或其他东西。
  • AtomicInteger 使用volatile 和一些底层同步。所以在这种情况下,我不清楚它的开销与Integer 的装箱开销相比如何。您是否使用适当的基准检查了“版本 1 是真正的性能杀手”声明?
  • 我用 JMH 测试过。 github.com/tkobayas/jmh-example/blob/master/…~~~ Benchmark Mode Cnt Score Error Units ThreadLocalBenchmark.testAtomicInteger ss 20000 92.736 ± 1.461 us/op ThreadLocalBenchmark.testInteger ss 20000 111.812 ± 2.375 us/op~~~ AtomicInteger 更快。
【解决方案3】:

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

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

ThreadLocal<int[]> count = new ThreadLocal<>();
...
count.set(new int[1]);
...
count.get()[0] = 42;
...
count.get()[0] += 4711;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多