Portlet、HttpSession 和线程安全
我们的 portlet 将状态保存在 HttpSession 中,该状态由同一会话的所有请求处理线程共享。
portlet 规范 (JSR-168) 写道:
PLT.5.2.4.3 请求处理期间的多线程问题
Portlet 容器通过并发处理对同一个 Portlet 的并发请求 在不同线程上执行请求处理方法。 Portlet 开发人员必须 设计他们的 portlet 来处理来自多个线程的并发执行 任何特定时间的
processAction
和render
方法。
我想知道我应该如何实现这一目标?当然,我可以在 processAction
和 render
期间使用同步来实现互斥,但我不知道如何强制整个请求处理的原子性。特别是,我担心以下情况:
- 线程 1 执行 processAction,将数据加载到会话中以供稍后渲染
- 线程 2 执行 processAction,丢弃会话中的数据
- 线程 1执行
render
,从会话中读取要渲染的数据,并抛出 NullPointerException,因为准备好的数据不再存在......
通常如何防止这种情况?特别是,当使用 JBoss Portlet 桥来使 JSF 适应 Portlet 环境时?
Our portlets keep state in the HttpSession, which is shared by all request processing threads for the same session.
The portlet spec (JSR-168) writes:
PLT.5.2.4.3 Multithreading Issues During Request Handling
The portlet container handles concurrent requests to the same portlet by concurrent
execution of the request handling methods on different threads. Portlet developers must
design their portlets to handle concurrent execution from multiple threads from within theprocessAction
andrender
methods at any particular time.
I wonder how I am supposed to achieve that? Sure, I can use synchronization to achieve mutual exclusion during both processAction
and render
, but I don't see how I can enforce atomicity of request processing as a whole. In particular, I worry about the following scenario:
- Thread 1 executes
processAction
, loading data into the session for later rendering - Thread 2 executes
processAction
, discarding that data from the session - Thread 1 executes
render
, reading the data to render from the session, and throws a NullPointerException because the prepared data is no longer there ...
How is that scenario usually prevented? In particular, when using the JBoss portlet bridge to adapt JSF to a Portlet environment?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想说,如果有两个 portlet 操作相同的数据,尤其是一个读取它,而另一个删除它,那么设计中很可能存在严重缺陷。
然后,您可能想要存储每个 portlet/线程的数据,即,如果 portlet1 读取一些数据,您应该写入锁定它,直到读取完成,然后使用唯一密钥将其放入会话中。
如果删除应渲染的数据是合法的,那么您应该考虑到这一点并在渲染期间再次检查。
I'd say that if there are two portlets operating on the same data, especially one reading it while the other deletes it, there's most likely a serious flaw in the design.
You might then want to store the data per portlet/thread, i.e. if portlet1 reads some data you should write lock it until reading is finished and put it into the session using a unique key.
If it is legal to delete data that should be rendered, then you should account for that and check again during
render
.