Java 弹簧&x27;s延迟的结果setResult与超时的交互
我正在Tomcat上试验Spring的Java 弹簧&x27;s延迟的结果setResult与超时的交互,java,spring,tomcat,comet,spring-3,Java,Spring,Tomcat,Comet,Spring 3,我正在Tomcat上试验Spring的DeferredResult,我得到了疯狂的结果。是我做错了,还是春天或Tomcat里有虫子?我的代码很简单 @Controller public class Test { private DeferredResult<String> deferred; static class DoSomethingUseful implements Runnable { public void run() {
DeferredResult
,我得到了疯狂的结果。是我做错了,还是春天或Tomcat里有虫子?我的代码很简单
@Controller
public class Test {
private DeferredResult<String> deferred;
static class DoSomethingUseful implements Runnable {
public void run() {
try { Thread.sleep(2000); } catch (InterruptedException e) { }
}
}
@RequestMapping(value="/test/start")
@ResponseBody
public synchronized DeferredResult<String> start() {
deferred = new DeferredResult<>(4000L, "timeout\n");
deferred.onTimeout(new DoSomethingUseful());
return deferred;
}
@RequestMapping(value="/test/stop")
@ResponseBody
public synchronized String stop() {
deferred.setResult("stopped\n");
return "ok\n";
}
}
我不认为我做错了什么。Spring文档似乎表示可以随时调用setResult
,即使请求已经过期,也可以从任何线程(“
应用程序可以从其选择的线程生成结果”)
使用的版本:Linux上的Tomcat 7.0.39,Spring 3.2.2。这是一个很好的bug发现
为了更好地理解,只需添加更多关于bug()的信息 setResult()中有一个同步块,扩展到提交分派的部分。如果超时同时发生,这可能会导致死锁,因为Tomcat超时线程有自己的锁定,只允许一个线程执行超时或分派处理 详细说明: 当您在请求“超时”的同时调用“stop”时,两个线程正试图锁定DeferredResult对象“deferred”
如果另一个执行超时处理的线程已经获取了TomcatLock,那么该线程将等待获取“deferred”上的锁以完成setResult()
所以,我们最终陷入了一个典型的僵局状态 当DeferredResult被认为是提供异步响应的另一种方式时,对方法上的synchronized不太在意。告诉一个方法它是同步的假设是同步的行为,如果不小心的话会导致死锁。
synchronized
s是我原始代码的残余。为了确定这一点,我将它们移除并重新测试。它没有改变任何东西。我在上游报告了这个错误,这个错误已经在Spring3.2.3中修复。