1.线程安全
线程安全封装在共享数据内部
共享数据 有状态值 不在线程栈 加锁
单个状态值 现有线程安全类 ,多个状态值 不变性条件涉及的状态值 用同一把锁
2对象的共享
发布: 对象的引用传给作用域外。 方法参数 返回值,静态变量
逸出:不应该发布的对象被发布了。构造方法中创建内部类实例,启动线程,拥有不完整this。
安全发布:
①线程封闭: 局部变量(线程栈中) threadlocal
②volatile(可见性) + 不可变类 : 想改变只能重新创建对象,并保证可见性
③线程安全共享: 线程内部实现同步
④保护对象:加锁
第三:Spring中的有状态(Stateful)和无状态(Stateless)
1.通过上面的分析,相信大家已经对有状态和无状态有了一定的理解。无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。
2.默认情况下,从Spring bean工厂所取得的实例为singleton(scope属性为singleton),容器只存在一个共享的bean实例。
3.理解了两者的关系,那么scope选择的原则就很容易了:有状态的bean都使用prototype作用域,而对无状态的bean则应该使用singleton作用域。
4.如Service层、Dao层用默认singleton就行,虽然Service类也有dao这样的属性,但dao这些类都是没有状态信息的,也就是相当于不变(immutable)类,所以不影响。Struts2中的Action因为会有User、BizEntity这样的实例对象,是有状态信息的,在多线程环境下是不安全的,所以Struts2默认的实现是Prototype模式。在Spring中,Struts2的Action中,scope要配成prototype作用域。
同步容器 fail-fast 容器改变 抛出异常 有些操作需要加锁
并发容器 弱一致性 不抛出异常 并发访问 效率高
一般用concurrenthashmap ,分段锁, 并发读写不同的段,,需要独占访问 用 hashmap, synchronizedmap
copyonwritelist 写入时复制 ,新建一个容器, 适合遍历多的情况,例如观察者模式遍历通知