ThreadLocal的意义与本质

threadlocal众所周知,可以把变量绑定到某一线程上,thread里有个全局变量threadlocalmap,范型为,threadlocal在执行set方法时先获取当前线程,拿到threadlocalmap,以以身为key把值放到map中,从而实现变量与线程的绑定。

关于threadlocal的用法,有这样几种说法。

1.传递上下文变量,减少程序复杂度 

 2.空间换时间,解决并发下对临界资源的访问问题。

这两种说法都对,都很切题,一个从应用角度考虑,一个从底层远离考虑。但我认为,threadlocal的真正意义是它解决了无状态问题。一听到无状态大家肯定马上联想到http协议,http协议就是无状态的,不会保存通信两端的状态信息,也赋予了http协议强大的灵活性。严格上来讲,我们现在所编写的servlet都是无状态的,虽然被springMVC等等框架封装了一层。这里可以借用http协议中session的概念,session其实就是http无状态的一种解决方案,由于服务端需要保存用户数据,而http协议又无法做到这一点,所以间接的通过保存在客户端cookie中的jsessionid来识别用户,每次请求jsessionid会被写在http header中发送给服务端,服务端根据jsessionid在内存中拿到相应的用户信息。这种方法虽然好用,但破坏了http协议无状态的特性,经典的restful架构就不推荐使用session,而推荐使用token作为解决方案,但由于token本身的特性,也带来了一些额外的问题。但工程设计上的东西很多时候并不能和教科书上的论文完美契合,因此不必刻意迎合restful而嫌弃session,所谓“不管黑猫白猫,能抓住耗子就是好猫”即是如此,选择最合适的架构才是最好的。

打个比方,基于servlet编程模型下产生的无状态问题,servlet在设计时并未考虑本身的状态问题,而是提供了一个接口singleThreadModel,实现了这个接口的servlet将不会是默认单例的,web容器会创建多个servlet对象以实现多种状态的servlet。在jsr—340中该接口被废弃了,可能是由于大量servlet对象的内存占用问题,官方建议开发者选择其他方法解决servlet的状态问题,其中一个方法即为临界区资源加锁,这种方法确实可以实现,但加锁强行将servlet的执行串行化,会导致请求效率极低,会导致web容器普遍采用的线程池和nio毫无意义。因此也极度不建议使用,最后一种即采用threadlocal保存servlet bean状态,通过空间换时间的方法,以一点内存占用为代价解决了这个问题,我觉得这才是threadlocal的真正用法,而不是方便变量在让上下文之间的切换。

不过基于mvc的面向过程式项目开发,比如传统的SSM项目,已经不存在这个问题了,因为从头到尾那些java bean都是贫血模型的,有的只有数据没有行为如pojo,有的只有行为没有数据如service,controller。也就是说整个架构跑起来可能都没有一个真正的鲜活的对象,那还何来有无状态的问题呢?这种工程式的思维把java这样一门oop语言当做面向过程来用,好处是标准化,降低开发门槛,降低对开发者的要求,代码复杂度不高,有利于维护,但采用数据组装这种办法也天然产生了危险的并发问题。。。待续

以上都是吃饱了撑的xjb扯得,大家愿意看就看吧,觉得写太垃圾尽管喷吧,我也只是个菜鸡

你可能感兴趣的:(并发编程)