【问题标题】:Synchronize multiple-threads to ensure only one of them caches a result (using spring cache)?同步多线程以确保其中只有一个缓存结果(使用弹簧缓存)?
【发布时间】:2020-12-20 01:45:26
【问题描述】:

假设我有一个方法A,也就是@Cacheable,但是很多线程可能同时使用相同的参数访问它。

我想确保只有第一个线程创建缓存,以防止所有其他线程处理他们的请求。

我当然可以使用同步来包装方法。但这会导致所有线程都会阻塞该方法。而且,synchronized 不会包装 @Cacheable AOP。

那么,有没有办法使用开箱即用的 Spring 来实现呢?

【问题讨论】:

  • 您使用的是哪个缓存提供程序?
  • @dnault Redis 和 Redisson 的 CacheManager 实现。

标签: java spring spring-cache redisson


【解决方案1】:

参见@Cacheable 注释sync 属性(Javadoc)和Reference Documentation 相同。

此外,正如 @dnault 所暗示的,它还依赖于缓存提供程序的实现。并非所有缓存提供程序都支持此选项,因此请检查您的缓存提供程序是否支持。

关于...

我想确保只有第一个线程创建缓存,以防止所有其他线程处理他们的请求。

缓存同步不是在“创建缓存本身”时进行同步,而是在缓存的条目(按键)上进行同步。

缓存是Map(即键/值存储/数据结构)。

如果我有一个有利于缓存的应用服务方法,例如:

@Service
class UserService {


  @Cacheable(cacheNames = "UsersByName", sync = true)
  User findBy(String name) {
    ...
  }
}

如果给定的话……

Thread A: userService.findBy("janeDoe");

Thread B: userService.findBy("jonDoe");

Thread C: usesService.findBy("janeDoe");

只有 Thread C 会阻塞并等待 Thread A 计算的缓存结果。

线程 B 将不间断地继续查找或计算“jonDoe”的User

另请注意,大多数缓存提供程序都希望“UsersByName”缓存在应用程序配置/启动时已经存在。

【讨论】:

  • 约翰的回答很棒,非常感谢。尤其是这部分...“另外,正如@dnault 所暗示的,它还依赖于缓存提供程序的实现。并非所有缓存提供程序都支持此选项,因此请检查您的缓存提供程序是否支持。”
猜你喜欢
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
  • 2014-05-13
相关资源
最近更新 更多