【问题标题】:Are ehcache putAll Operations Thread Safe and Atomic?ehcache putAll 操作线程安全且原子吗?
【发布时间】:2016-08-28 15:51:49
【问题描述】:

文档说 ehcache 是线程安全的。据我了解,如果thread A 更新缓存,这些更新将始终对其他线程可见。

但我想知道putAll 操作是否是线程安全和原子的?比如说,我想通过调用putAll 并传递带有实际值的Map 来更新我的缓存。 说,我想在更新缓存时从缓存中获取一些价值。我会收到旧值还是等到缓存更新并收到新值?

【问题讨论】:

  • 线程安全和原子是两个不同的概念。原子操作必然是线程安全的,但线程安全并不要求给定的操作是原子的。只要构成较大操作的原子操作使缓存处于一致状态(例如,没有创建但未填充的条目),那么较大的操作可能被认为是线程安全的。基于以下内容:ehcache.org/apidocs/2.9/net/sf/ehcache/… 我推测 putall 不是原子的

标签: java multithreading ehcache


【解决方案1】:

当操作只能完全执行或根本不执行时,操作是原子的。根据Interface EhcacheputAll 操作不是原子的。

如果在集合中遇到空元素或空键,此方法将抛出 NullPointerException,并且可能会导致部分完成(因为可能只放置了一些元素)。

关于 ehcache 是否是线程安全的。 Ehcache 专门设计为线程安全的。以Cache 实现为例。

缓存是线程安全的。

但要注意线程安全并不意味着同步。那么有什么区别呢?

线程安全意味着一个类可以在多个线程中使用而不会出现任何错误或问题。

同步意味着一个或多个方法只能从一个线程同时使用。

putAll 是什么意思,比如说get 电话。这两种方法都是线程安全的,但它们不同步。

因此,您无法确定线程 A 调用 putAll 和线程 B 调用 get 之后,putAll 是否在 get 之前执行。

【讨论】:

  • “你不能确定线程 A 调用 putAll 和线程 B 调用 get 之后 putAll 在 get 之前执行”,如果方法是同步的,你也不能确定这一点。同步无非是实现线程安全(和原子性)的一种方式。 putAll 的描述排除它是原子的。实现原子操作的最简单方法是锁定资源。如果您这样做,您可以保证其他线程将始终看到指定的更改或根本看不到任何更改。根据您的定义, Concurrent*Set.add() 方法也不能是原子的
  • @Voo,我认为我们对原子操作有不同的定义。当然,如果两个方法都是同步的,你可以确定如果一个线程首先调用一个方法,另一个线程调用会被阻塞,直到第一个线程的方法调用完成。
  • 如果你的定义使得 putAll 不可能是原子的,那它就不可能是正确的,因为让它原子化很简单(只需锁定所有内容)。是的,如果遇到空元素,它会抛出异常,但是唯一有意义的原子定义是其他线程可以看到所有修改或没有。但是你当然可以记录一个方法来抛出并只做一些工作,同时仍然是原子的
  • @Voo,这不是我的定义,它是 putAll 的实现,它使其成为非原子操作'[...] 部分完成可能导致 [...]'。让操作成为原子操作是否微不足道也不是问题。
  • 部分完成是该调用的最终结果。这很简单:如果指定的行为是应该插入三个元素(因为第四个为空,所以剩余的两百万个元素由于异常而被忽略)并且您可以看到零个或所有三个插入的元素,该函数是原子的,如果你能看到两个元素,但看不到第三个,那就不是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多