同步多个线程,以确保只有一个线程对结果进行缓存(使用 Spring 缓存)。

huangapple go评论72阅读模式
英文:

Synchronize multiple-threads to ensure only one of them caches a result (using spring cache)?

问题

假设我有一个方法A,它被标记为@Cacheable,但是许多线程可能同时使用相同的参数访问它。

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

当然,我可以使用synchronized来包装这个方法。但是这会导致所有的线程都在这个方法上被阻塞。而且,synchronized不会包装@Cacheable的AOP。

那么,有没有一种使用Spring开箱即用的方法来实现这个?

英文:

Let's say that I have a method A, which is @Cacheable, but many threads may access it at the same time with the same parameters.

I'd like to ensure that only the first thread creates the cache, to prevent all of the other thread from processing their requests.

I could use synchronized to wrap the method of course. But that would cause all of the threads would block on that method. And also, synchronized will not wrap the @Cacheable AOP.

So, is there a way using Spring out-of-the-box to implement this?

答案1

得分: 2

查看@Cacheable注解的sync属性(Javadoc)和参考文档以获取相同信息。

另外,正如**@dnault**所暗示的,这也取决于缓存提供程序的实现。并非所有的缓存提供程序都支持这个选项,因此请检查您的缓存提供程序是否支持。

关于……

> "我希望确保只有第一个线程创建缓存,以防止其他所有线程处理其请求。"

缓存同步与"缓存本身的创建"无关,而是与缓存的条目(按键)的同步有关。

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

如果我有一个适合缓存的应用程序服务方法,例如:

@Service
class UserService {

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

那么如果有……

线程 A: userService.findBy("janeDoe");

线程 B: userService.findBy("jonDoe");

线程 C: usesService.findBy("janeDoe");

只有线程 C 会在由线程 A 计算的缓存结果上阻塞和等待。

线程 B 将继续查找或计算与"jonDoe"相关的User,而不会受到干扰。

还要注意,大多数缓存提供程序希望在应用程序配置/启动时已经存在"UsersByName"缓存。

英文:

See the @Cacheable annotation sync attribute (Javadoc) and Reference Documentation for the same.

Also, as @dnault alluded to, it is also caching provider implementation dependent. Not all caching providers may support this option, so check that your caching provider does.

Regarding...

> "I'd like to ensure that only the first thread creates the cache, to prevent all of the other thread from processing their requests."

Cache synchronization is not about synchronizing on the "creation of the cache itself", but rather about synchronizing on the entry (by key) that is cached.

A cache is a Map (i.e. a key/value store/data structure).

If I have a application service method that is conducive to caching, for example:

@Service
class UserService {


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

Then if given...

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

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

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

Only Thread C will block and wait on the cache result computed by Thread A.

Thread B will proceed to lookup or compute the User for "jonDoe" uninterrupted.

Also note, most caching providers expect the "UsersByName" cache to already exist at application configuration/startup time.

huangapple
  • 本文由 发表于 2020年9月1日 07:04:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/63679278.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定