【问题标题】:Make thread-safe a normal class with ThreadLocal<T>使用 ThreadLocal<T> 使线程安全成为普通类
【发布时间】:2010-12-29 21:05:19
【问题描述】:

我有一个设计为由单个线程访问的普通类,我想让它thread-safe 这么多线程可以同时使用一个实例。我会将一些类级别的方法和变量设为静态并使用locks 将它们设为thread-safe。此外,默认情况下使用局部变量的方法是安全的(每个线程都有自己的堆栈)。

我的问题是关于旧班级的properties,或者更普遍的是任何non-static 变量。我可以简单地使用 ThreadLocal&lt;T&gt; 并且每个线程都有自己的一组 properties 吗?我肯定会在setters 中使用locks 和其他thread-safety 问题(我假设getters 是安全的)。

ThreadLocal&lt;T&gt; 是性能杀手吗?

【问题讨论】:

  • 不描述这个类的作用,以及为什么会有多线程的干扰,没有人能给你一个好的答案。
  • 您认为 ThreadLocal 究竟做了什么?因为我不认为它做你认为它做的事。你能解释一下为什么你认为线程本地存储是正确的解决方案吗?
  • @Eric:我读到它使变量成为线程的本地变量。因此,我们拥有与正在运行的线程数一样多的属性。所以对象可以有每个线程的状态。
  • 那么听起来您正在寻找正确的东西。但是,我担心您的评论,即锁定需要在设置器上进行,而不是在获取器上。这没有任何意义。如果 getter 在 setter 设置属性进行到一半时运行怎么办?如果您要使用锁,那么只有始终使用它们才有意义。
  • 关于性能问题:你是唯一能回答的人。编写一些基准测试并测量实际情况下的性能,看看您的用户是否可以接受该性能。我们不知道您使用的是什么硬件,消耗了多少内存,也不知道您的客户是否需要能够在两分钟或两微秒内给出正确答案的代码。

标签: c# properties thread-safety thread-local


【解决方案1】:

Getter 并不像你想象的那么安全。 Java 内存模型为每个线程提供了它自己的堆视图,因此如果您不同步对变量的访问,那么线程可能会读取过时的数据。制作变量volatile 将防止过时的读取,并且适用于原语,但volatile 不会使访问原子化。

java.util.concurrent 包中有很多类可能会对您有所帮助。编写线程安全的代码很棘手,所以我建议你买一本关于这个主题的好书。 Brian Goetz 的《Java concurrency in practice》很不错。

【讨论】:

  • 有人将 Java 添加到问题标签(已编辑)。这是一个 C# 类。
  • 啊。好吧,如果你曾经在 Java 中做过任何事情,那么请牢记内存。
【解决方案2】:

这并不是线程本地人的真正用途。它们适用于每个线程都有自己的数据的情况。

在您的情况下,我建议将字段类型更改为 Map&lt;Object, Object&gt; 并使用 Collections.synchronizedMap 以使其线程安全。

【讨论】:

  • 有人将Java 添加到问题标签(已编辑)。这是一个C# 类。
猜你喜欢
  • 1970-01-01
  • 2015-05-30
  • 2016-09-23
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多