ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Session管理之ThreadLocal之线程安全

2022-08-01 20:04:52  阅读:147  来源: 互联网

标签:实例 Session ThreadLocal session 线程 public



在各种Session 管理方案中, ThreadLocal 模式得到了大量使用。ThreadLocal 是 Java中一种较为特殊的线程绑定机制。通过ThreadLocal存取的数据,总是与当前线程相关。
也就是说,JVM 为每一个执行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出 现的并发訪问问题提供了一种隔离机制。
首先,我们须要知道。SessionFactory负责创建Session,SessionFactory是线程 安全的,多个并发线程能够同一时候訪问一个SessionFactory 并从中获取Session 实例。而
Session并不是线程安全,也就是说。假设多个线程同一时候使用一个Session实例进行数据存取。 则将会导致Session 数据存取逻辑混乱。

 

以下是一个典型的Servlet,我们试图通过一个类 变量session实现Session的重用,以避免每次操作都要又一次创建:

public class TestServlet extends HttpServlet {
    private Session session;
    public void doGet( HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
        session = getSession();
        doSomething();
        session.flush();
    }
    public void doSomething(){
    ......//基于session的存取操作
    }
}

代码看上去正确无误,甚至在我们单机測试的时候可能也不会发生什么问题。但这种代 码一旦编译部署到实际执行环境中,接踵而来的莫名其妙的错误非常可能会使得我们摸不找头脑。
问题出在哪里?
首先,Servlet 执行是多线程的,而应用server并不会为每一个线程都创建一个Servlet 实例,也就是说,TestServlet在应用server中仅仅有一个实例(在Tomcat中是这样,其它的
应用server可能有不同的实现),而这个实例会被很多个线程并发调用,doGet 方法也将被不 同的线程重复调用,可想而知,每次调用doGet 方法,这个唯一的TestServlet 实例的
session 变量都会被重置,线程A 的执行过程中,其它的线程假设也被执行,那么session 的引用将发生改变。之后线程A 再调用session。可能此时的session 与其之前所用的
session就不再一致,显然,错误也就不期而至。 ThreadLocal的出现,使得这个问题迎刃而解。 我们对上面的样例进行一些小小的改动:

public class TestServlet extends HttpServlet {
    private ThreadLocal localSession = new ThreadLocal();
    public void doGet( HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
        localSession.set(getSession());
        doSomething();
        session.flush();
    }
    public void doSomething(){
    Session session = (Session)localSession.get();
    ......//基于session的存取操作
    }
}

能够看到,localSession 是一个ThreadLocal 类型的对象。在doGet 方法中,我们 通过其set 方法将获取的session 实例保存,而在doSomething 方法中。通过get 方法取
出session实例。 这也就是ThreadLocal的独特之处。它会为每一个线程维护一个私有的变量空间。

实际上。 事实上现原理是在JVM 中维护一个Map。这个Map的key 就是当前的线程对象,而value则是
线程通过ThreadLocal.set方法保存的对象实例。

当线程调用ThreadLocal.get方法时。 ThreadLocal会依据当前线程对象的引用。取出Map中相应的对象返回。


这样,ThreadLocal通过以各个线程对象的引用作为区分,从而将不同线程的变量隔离开 来。

标签:实例,Session,ThreadLocal,session,线程,public
来源: https://www.cnblogs.com/yaowen/p/16541658.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有