这是线程安全的吗?

发布于 2024-10-16 10:09:44 字数 794 浏览 1 评论 0原文

我想让我的类成为线程安全的,而不需要很大的开销。 这些实例很少会同时使用,但也可能会发生。 大多数类都是不可变的,只有一个可变成员用作缓存:

private volatile SoftReference<Map<String, Something>> cache
    = new SoftReference(null);

它在构造函数中分配(不共享),就像

Map<String, Something> tmp = new HashMap<String, Something>();
tmp.put("a", new Something("a");
tmp.put("b", new Something("b");
cache = new SoftReference(tmp);

分配后,映射永远不会被修改。

当两个线程并行计算缓存时,这没有问题,因为值是相同的。 单词完成两次的额外开销是可以接受的。

当一个线程看不到另一个线程计算的值时,它会计算出不必要的值,这是可以接受的。 由于不稳定,这种情况不会发生。 当一个线程看到另一个线程计算的值时,就很好了。

唯一可能的问题是线程看到不一致的状态(例如部分填充的地图)。 这会发生吗?

注意:

  1. 我真的希望整个地图被软引用,这里使用软键或值的地图没有用处。

  2. 我了解 ConcurrentHashMap,并且可能会使用它,但我很好奇,如果仅使用 volatile 才有效。

I want to make my class thread-safe without large overhead.
The instances will be seldom used concurrently, but it may happen.
Most of the class is immutable, there's only one mutable member used as a cache:

private volatile SoftReference<Map<String, Something>> cache
    = new SoftReference(null);

which gets assigned in the constructor (not shared) like

Map<String, Something> tmp = new HashMap<String, Something>();
tmp.put("a", new Something("a");
tmp.put("b", new Something("b");
cache = new SoftReference(tmp);

After the assignment, the map gets never modified.

It's no problem, when two threads compute the cache in parallel, since the value will be the same.
The additional overhead of the word done twice is acceptable.

When a thread wouldn't see the value computed by another tread, it'd compute it unnecessary, and this is acceptable.
This wouldn't happen because of volatile.
When a thread sees value computed by another tread, it's fine.

The only possible problem would be a thread seeing inconsistent state (e.g. a partly filled map).
Can this happen?

Notes:

  1. I really want the whole map being softly referenced, there's no use for a map using soft keys or values here.

  2. I know about ConcurrentHashMap and will maybe use it anyway, but I'm curious, if using volatile only works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

缘字诀 2024-10-23 10:09:44

唯一可能的问题是
线程看到不一致的状态(例如
部分填充的地图)。这会发生吗?

不可以。在线程内执行的操作必须像按顺序执行一样执行。写入易失性变量发生在读取该值之前。因此,映射的初始化发生在任何线程从字段读取对映射的引用之前。

The only possible problem would be a
thread seeing inconsistent state (e.g.
a partly filled map). Can this happen?

No. Actions performed within a thread must be performed as if they had been executed in order. Writing a volatile variable happens-before any read of that value. Hence, initialization of the map happens-before any thread reading the reference to the map from the field.

放肆 2024-10-23 10:09:44

使用软引用的问题是,GC 后您可能会丢失整个映射/缓存。这意味着您的应用程序的性能可能会受到严重影响。您最好使用具有驱逐策略的缓存,这样就不会出现此问题。

易失性并不会使这里的任何操作变得安全。

您还没有显示所有代码,也许我们可以提供一些关于如何改进代码的建议,例如您的示例代码应该编译;)

The problem with using a soft reference is that you can lose the whole map/cache after a GC. This means the performance of your application can be hit very hard. You are better off using a cache with an eviction policy so that you never have this problem.

The volatile doesn't make any operation safe here.

You haven't shown all your code, perhaps we could offer some suggestion on how you could improve your code e.g. your sample code should compile ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文