《Java并发编程实战》 线程安全类的设计
在设计线程安全类的过程中,需要包含以下三个基本要素:
- 找出构成对象状态的所有变量;
- 找出约束状态变量的不变性条件;
- 建立对象状态的并发访问管理策略;
对象封装它拥有的状态,并拥有这些状态的所有权或者说控制权,它决定采用何种加锁策略来维持变量状态的完整性,然而,如果发布了某个可变对象的引用,那么就不再拥有独占的控制权,最多是共享控制权。
一般对于从构造器或者从方法中传递进来的对象,类并不拥有这些对象,除非这些方法是被专门设计来转移传递进来的对象的所有权。例如容器,容器通常表现出一种所有权分离的形式,其中容器拥有其自身的状态,而客户代码则拥有容器中各个对象的状态。
比如Servlet
框架中的ServletContext
,ServletContext
为Servlet
提供了类似于Map
形式的对象容器服务,在ServletContext
中可以通过名称来注册或获取应用程序的Attribute
对象,但这些对象由应用程序拥有,ServletContext
容器只是替应用程序保管它们。
ServletContext
必须是线程安全的,因为它肯定会被多个线程同时访问。因此当调用setAttribute
或getAttribute
时,Servlet
不需要使用同步。而如果Attribute
对象本身不是线程安全的,那么在getAttribute
之后为防止多线程并发访问,访问者依然需要使用同步。
HttpSession
与ServletContext
有类似的功能,但它可能更加严格,会要求保存的Attribute
对象是线程安全的,因为Servlet
容器可能与Web Application同时访问HttpSession
中的对象,而且对于Session
通常会有复制或持久化之类的操作,所以要求这些对象是线程安全的。