【问题标题】:Can same Ehcache object of same CacheManager be used by multiple threads?同一个 CacheManager 的同一个 Ehcache 对象可以被多个线程使用吗?
【发布时间】:2018-01-31 17:28:51
【问题描述】:

我创建了一个Cache 对象,该对象将String 存储为键,将序列化对象存储为值。

Cache(String--->Object) 

我正在尝试运行三个 Akka 线程,它们以同步的方式检索和写入同一个 Ehcache 对象。

Thread 1- synchronized (LockForEhcache){ 
              serializedObj = cachename.get("key"); //--- this returns an Object            
          }
          //modify the serializedObj here....
          //Again store the modify Object in the Cache
          synchronized (LockForEhcache){
              cachename.clear();
              cachename.put("key",serializedObj);
Thread 2- synchronized (LockForEhcache){ 
              serializedObj = cachename.get("key"); //--- this returns null
          }
Thread 3- synchronized (LockForEhcache){ 
              serializedObj = cachename.get("key"); //--- this returns null
          }

但只有一个线程获取存储在Cache 中的值。对于其余的线程,它会抛出一个NullPointerException。我不知道为什么。

【问题讨论】:

  • 不确定这些 synchronized (LockForEhcache) 是关于什么的...但是 ehcache 不需要您同步访问,使用它是完全线程安全的...如果另一方面,您试图同步这些线程,以便线程 1 在 t2 和 t3 到达 get 之前放置,这不会按原样工作。还是只是说你做了什么?
  • 我正在使用锁,因此除非线程 1 完成其 put ,否则其他线程不会尝试 get 。为什么这不起作用?
  • 好吧,也许我在这里“猜测”太多了...... t1 是主线程,而 t2 和 t3 是从中分离出来的吗?如果不是,并且所有三个线程都在竞相获取锁,那么这可能工作,但不确定(即你不能保证 t1 首先获取锁并安装映射)。如果 t1 产生另外两个线程,它仍然需要在安装映射之后 这样做。锁只提供排除,不提供排序。

标签: java concurrency ehcache ehcache-bigmemory ehcache-3


【解决方案1】:

首先,缓存不是存储。所以你不能指望缓存总是返回最新的数据。由于不同的原因,它可能会返回 null。

现在,除非发生某些驱逐或过期,否则数据应该在那里。所以我需要一个完整的例子来告诉你发生了什么。

我的第一个问题是:为什么要清除并放置?为什么不只放?我们是否同意 clear 将清除所有条目?您的缓存中只有一个条目?

【讨论】:

  • 这里,clear 将删除缓存中存储的所有条目并存储最新的条目。因此,每次只有一个条目会出现在缓存中。
  • 为什么不直接覆盖它们呢?你需要这是原子的吗? (完全替换同步)
  • 我删除了同步块,现在它可以正常工作,没有任何空指针异常。但是,当线程 1 执行 put 时,如何确保 get 不被其他线程调用?
  • 我认为你不在乎。 Ehcache 会处理这个问题。 put 有一个之前和一个之后。因此,新值对任何人都不可见,然后对每个人都可见。添加更高的同步只会扩大锁定范围。
  • 如果删除同步块就是你所做的,那么上面的代码 sn -p 是不完整的。而且很可能您的代码在某些方面仍然很活泼……话虽如此,您真的在乎吗?这段代码甚至试图证明/做什么?
【解决方案2】:

我现在才看到第一个线程也以get 开头,那么这是否意味着安装了映射总是?如果是这样,您确定其他线程实际上正在使用相同的Cache 实例吗?

【讨论】:

  • 是的,所有线程都在使用同一个缓存实例。您能否详细说明已安装映射是什么意思?这是否意味着一旦我从 Cache 执行 get,我对该序列化对象所做的所有更新都将存储在 Cache 中而不使用 put ?
  • 如果你存储(不可变的)序列化形式,那么没有。不会自动更新任何内容。另一方面,如果您存储实际的可变对象,那么...这取决于:只要引用在堆上(即它取决于缓存的拓扑和可能的时间),那么对对象的任何更改 可能对其他线程可见。 put 将为该键引入与 get 的发生前关系。
  • 如果引用在磁盘上会发生什么?
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 2023-03-27
  • 2020-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多