根据Java,这个方法是否是线程安全的

时间:2016-01-27 14:11:19

标签: java spring gwt

如果两个线程在服务器上访问此方法,它是否是线程安全的?线程来自GWT计时器。

public UserDTO getUserFromSession()
{
        UserDTO user = null;
        HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
        HttpSession session = httpServletRequest.getSession();
        Object userObj = session.getAttribute("user");
        if (userObj != null && userObj instanceof UserDTO)
        {
            user = (UserDTO) userObj;
        }
        return user;
}

4 个答案:

答案 0 :(得分:2)

如果方法不能访问外部(方法)共享变量,则该方法是线程安全的。

代码中的问题可能出在那行代码中:

HttpServletRequest httpServletRequest = this.getThreadLocalRequest();

因为this.getThreadLocalRequest()似乎访问共享变量。 为了确保发表全班,但我能看到的是不是线程安全的

在解释说明getThreadLocalRequest方法安全返回HttpServletRequest的注释之后,代码仍然不是线程安全的。

根据此article,事实HttpSession不是线程安全的:基本上会话可以在代码执行期间更改。 例如,您也可以在会话失效后返回用户。 想象一下这个步骤:

thread 1                                                thread 2
----------------------------------------------          --------------
Object userObj = session.getAttribute("user");

                                                        session.invalidate();

if (userObj != null && userObj instanceof UserDTO) {
    user = (UserDTO) userObj;
}
return user;    

如果会话被另一个线程无效,那么最后您也会返回一个用户。

答案 1 :(得分:0)

这种方法本身是无害的。即使您没有线程本地请求,它也将是无害的。我看到的唯一问题是在实例化时检索属性“user”的关闭情况,另一个线程在第一个线程退出方法之前擦除属性“user”clean。您将在一个线程中处理用户实例,而在另一个线程中,由于不再定义“user”属性,您可能会以不同方式执行逻辑。

那就是说,我真诚地怀疑会出现任何问题,因为这些都是读取和不写入而没有副作用的方法。请注意,有几个线程可能(并且可能会)处理相同的用户实例,因此在这种情况下,您需要在同步块下对用户保持线程敏感操作。

答案 2 :(得分:0)

是的,就只有你给定的方法而言,它是线程安全的。 getThreadLocalRequest()是您当前线程的本地线程,getSession()也是线程安全的。 即使从会话中获取userObj也不会导致问题。

但毕竟多次调用可以访问相同的UserDTO对象。 因此,您需要确保此对象中的可能更改以线程安全方式完成,或者该对象是不可变的。

答案 3 :(得分:0)

该方法看似线程安全,但它不是,但是以更微妙的方式:

虽然getSession()和会话是安全的,但会话及其内容不是。

您正在寻找的会话可以随时消失。仅检查此方法是不够的,还要检查所有其他会话相关对象。

在高负载情况下,您需要注意,getuser函数不会动态重新创建会话。

getSession(false)将负责此事。在这种情况下,您将对返回的会话进行空检查并中止您的通话。

之前由其他人声明的用户对象是另一项责任。