Java 是春天';当涉及逐出时,是否可以安全使用缓存注释?

Java 是春天';当涉及逐出时,是否可以安全使用缓存注释?,java,spring,caching,spring-cache,Java,Spring,Caching,Spring Cache,我使用的是Spring4.0.3,并利用了由Ehcache2.8.1支持的缓存抽象特性 我担心方法级注释@Cacheable和@cacheexecute在编辑缓存时可能无法正确锁定缓存,从而导致线程安全问题。我下面的测试似乎证实了这一点。我的问题是,我是否误用了这个框架或者误解了我的测试结果?或者我的结论正确吗?注释不会导致缓存被正确锁定,因此使用@cacheexecute不能保证将来的读取是有效的 测试: 创建数据库表以存储计数器值 create table counter ( cou

我使用的是Spring4.0.3,并利用了由Ehcache2.8.1支持的缓存抽象特性

我担心方法级注释
@Cacheable
@cacheexecute
在编辑缓存时可能无法正确锁定缓存,从而导致线程安全问题。我下面的测试似乎证实了这一点。我的问题是,我是否误用了这个框架或者误解了我的测试结果?或者我的结论正确吗?注释不会导致缓存被正确锁定,因此使用
@cacheexecute
不能保证将来的读取是有效的

测试:

创建数据库表以存储计数器值

create table counter
(
    counter integer
);
insert into counter values(0);
<cache name="counter"
    eternal="true"
    maxElementsInMemory="1"/>
在ehcache.xml中创建一个条目以缓存计数器值

create table counter
(
    counter integer
);
insert into counter values(0);
<cache name="counter"
    eternal="true"
    maxElementsInMemory="1"/>
在两种不同的场景下遵循这三个步骤——首先从控制器方法中删除缓存注释,然后将它们添加回

  • 访问
    /incrementcounter
  • 在一个浏览器选项卡中,访问
    /viewcounter
    ,然后在启动此请求后,立即访问另一个选项卡中的
    /incrementcounter
  • 访问
    /viewcounter
  • 测试结果

    Expected result: 2
    Actual result without caching: 2
    Actual result with caching: 1
    

    with缓存结果错误,是吗?

    缓存抽象中没有锁定。你是,我们已经在内部就支持它的成本进行了重要的头脑风暴。事实证明,它远不是简单的,在这种抽象中使用锁可能非常棘手,尤其是以“通用”的方式。此外,缓存供应商花费大量资源来支持此类用例,这是有原因的


    目前我的最佳猜测是,如果您想要这些功能,您需要使缓存具有事务性。不过,在将其与抽象结合使用时会遇到一些问题,请特别检查目前正在进行的工作。

    不,这是我所期望的。选择时的
    计数
    为1(之后更新)。该值被返回,因此被缓存。@M.Deinum我认为您讨论的是步骤2的结果。是的,此时,/viewcounter应显示值1。但我说的是第三步的结果。在对/incrementcounter执行两次调用之前,该请求不会启动,因此正确的结果应该是值2。对于步骤3,该值仍然是1,因为这是缓存的值。@M.Deinum我理解为什么会看到1,但我将其称为并发错误。我认为reads应该始终返回启动读取时的实际值。如果第2步中的读写操作已被锁定以防止交错,则第3步将显示正确的结果。我的观点是,我假设缓存注释会为我实现这种锁定,而这种假设似乎是错误的。我仍然没有看到问题。如果调用一个方法,则查询结果为1。在这两者之间,执行数据库更新和缓存逐出。线程仍在等待。。。然后它返回,这就是缓存结果的点。对
    /viewcounter
    的第二次调用返回缓存的结果。如何处理(或不处理)锁定取决于使用的缓存实现。Spring只委托给底层机制,它只是一个包装器,不添加功能。