相关疑难解决方法(0)

HttpSession中的同步是否可行?

更新:解决方案后问题.

题:

通常,同步是在JVM内串行化并行请求,例如

private static final Object LOCK = new Object();

public void doSomething() {
  ...
  synchronized(LOCK) {
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

在查看Web应用程序时,"JVM全局"范围上的某些同步可能会成为性能瓶颈,仅在用户的HttpSession范围内进行同步会更有意义.

以下代码是否可能?我怀疑同步会话对象是一个好主意,但听到你的想法会很有趣.

HttpSession session = getHttpServletRequest().getSession();
synchronized (session) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

关键问题:对于处理来自同一用户的请求的所有线程
,是否保证会话对象是同一个实例

总结答案/解决方案:

看来会话对象本身并不总是相同,它依赖于servlet容器(Tomcat,Glassfish,...)的实现,并且该getSession()方法可能只返回一个包装器实例.

因此,建议使用存储在会话中的自定义变量作为锁定对象.

这是我的代码提案,欢迎提供反馈:

帮手类中的某个地方,例如MyHelper:

private static final Object LOCK = new Object();

public static Object getSessionLock(HttpServletRequest request, String lockName) {
    if (lockName == null) lockName = "SESSION_LOCK";
    Object result = request.getSession().getAttribute(lockName);
    if (result == …
Run Code Online (Sandbox Code Playgroud)

java session multithreading synchronization servlets

30
推荐指数
3
解决办法
2万
查看次数

使用request.getSession()作为锁定对象?

我有一些获取和设置会话属性的java代码:

Object obj = session.getAttribute(TEST_ATTR);
if (obj==null) {
  obj = new MyObject();
  session.setAttribute(obj);
}
Run Code Online (Sandbox Code Playgroud)

为了使这段代码成为线程安全的,我想将它包装在一个synchronized块中.但是我用什么作为锁定对象呢?使用会话是否有意义?

synchronized (session) {
  Object obj = session.getAttribute(TEST_ATTR);
  if (obj==null) {
    obj = new MyObject();
    session.setAttribute(obj);
  }
}
Run Code Online (Sandbox Code Playgroud)

java concurrency session locking thread-safety

11
推荐指数
1
解决办法
5369
查看次数

了解Goetz关于HttpSession线程安全的文章

参考Brian Goetz的文章是否所有状态Web应用程序都被破坏了?对于IBM developerWorks,我想参考这段代码

HttpSession session = request.getSession(true);
ShoppingCart cart = (ShoppingCart)session.getAttribute("shoppingCart");
if (cart == null) {
    cart = new ShoppingCart(...);
    session.setAttribute("shoppingCart", cart);
}        
doSomethingWith(cart);
Run Code Online (Sandbox Code Playgroud)

根据我的理解,这段代码不是线程安全的,因为它使用了check-then-act模式.但我有一个疑问:

是不是HttpSession在第一行完全原子的创建或检索?原子,我的意思是如果两个线程调用request.getSession(),一个将阻止.虽然两者都会返回相同的HttpSession实例.因此,如果客户端(移动/ Web浏览器)制作两个或调用相同的Servlet(执行上面的代码片段),您将永远不会遇到不同线程看到不同值的情况cart.

假设我确信它不是线程安全的,那么如何使这个线程安全?会AtomicReference有效吗?例如:

HttpSession session = request.getSession(true);
AtomicReference<ShoppingCart> cartRef = 
     (<AtomicReference<ShoppingCart>)session.getAttribute("shoppingCart");
ShoppingCart cart = cartRef.get();
if (cart == null) {
    cart = new ShoppingCart(...);
    session.setAttribute("shoppingCart",
         new AtomicReference<ShoppingCart>(cart));
}
doSomethingWith(cart);
Run Code Online (Sandbox Code Playgroud)

留言Merci!

java concurrency multithreading servlets

10
推荐指数
1
解决办法
5885
查看次数

在JSF 2中的requestScoped bean中显式创建会话

我对在JSF 2.x中的requestScoped bean中创建会话有疑问.我知道我们不需要在JSF 2.x中创建会话,因为我们可以直接使用sessionScoped bean来放置用户所需的数据.但我最近介绍了一个JSF代码,其中开发人员创建了session的实例变量并从facescontext获取会话,如下所示

 @ManagedBean
 @RequestScoped
 Public class someClass(){

 FacesContext facesContext = FacesContext.getCurrentInstance();
 HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);

 public void someFunction(){

 //Some code here..

 session.setAttribute("key","value");

 //Some code here..

 }

  //rest of the code here...
 }
Run Code Online (Sandbox Code Playgroud)

好吧,我告诉他们一个人不应该将"session"作为实例变量,也不需要在JSF 2中显式获取会话,而是使用sessionScoped bean.

对于第一个我给出了一个理由,"保持会话作为实例变量不是线程安全的",而对于第二个语句,我给出了"你正在为已经提供的JSF会话做一个解决方法".

我得到的反驳论点是,第一个原因"我们的网络应用是如此,因此不存在多线程问题".第二,我得到了"无论如何,一旦请求被处理,会话变量将被清除,所以这里没有任何错误.

我没有其他强项来纠正它.所以我的问题是,1)他们是否正确?2)我们应该以应该做的方式做任何其他具体原因吗?3)最后,任何可能促使他们使用这种方式的东西?

任何人都可以详细说明吗?请指正.谢谢

multithreading java-ee jsf-2 managed-bean

7
推荐指数
1
解决办法
4101
查看次数

如何避免竞争条件

什么是避免jsp中的竞争条件同时不减慢进程的最佳方法.我试过isThreadSafe = false synchronized(session)

但有没有其他替代解决方案可用?

java jsp

2
推荐指数
2
解决办法
6162
查看次数