在Java中共享ThreadLocal变量

时间:2011-04-27 10:33:24

标签: java concurrency thread-safety thread-local

在我的小应用程序中,我有两个类的线程 - 基本上是作家和读者。可以将多个读取器分配给单个写入器。作者通过写入chunkBuffer变量与读者进行互动。

现在,我无法完全解决线程安全问题:如果我不将chunkBuffer存储在静态ThreadLocal变量中,则所有读者都将共享一个chunkBuffer,不好。但是如果我将chunkBuffer存储在一个静态的ThreadLocal中,那么作为一个单独的线程的编写器将获得它自己的chunkBuffer副本并继续写入它,而它写的数据都不会到达读者。你能解释一下这里的问题是什么吗?非常感谢你。

编辑换句话说,有没有办法创建一个对于线程子类的每个实例(如ThreadLocal)都是唯一的字段,但是可以根据需要从其他线程访问?

2 个答案:

答案 0 :(得分:2)

不。

ThreadLocal用于线程私有数据。在您的情况下,您需要通信的对象,因此您需要其他类型的对象。

我认为最好使用的结构是同步队列:java.util.concurrent.LinkedBlockingQueue<E>

队列允许生产者插入数据和消费者来消费。如果它是同步的,它允许从不同的线程执行它而不破坏结构。

您可以在相关作者/读者之间共享队列:

Writer 1 -> queue 1 -> [readers A/B/C]

Writer 2 -> queue 2 -> [readers D/E/F]

每个作家和读者都有自己的主题。如果没有项目,每个读者将尝试从其队列阻止中获取一个项目。如果你需要更明智地管理你的读者,你可以尝试更复杂的方法,但我认为这是一个很好的起点。

答案 1 :(得分:0)

我认为您不想使用ThreadLocal变量。你真的需要一个通知机制。

Writer执行以下操作:

  1. 写给读者的chunkBuffer
  2. 通知读者新数据。
  3. 在java并发的东西中有很多方法可以做到这一点,但通常最简单和最安全的方法是使用ArrayBlockingQueue。在您的使用案例中,听起来每个Reader都有自己的ArrayBlockingQueue,它只需要读取队列。

    它当然取决于您的用例。是否有必要始终处理最新数据,还是需要处理每次写入chunkBuffer?这些问题对于确定您需要的机制是必要的。

    注意:@helios提到同步队列的道具,希望我的回答能增加价值。