要编写线程安全的代码,其核心在于要对访操作进行管理,特别是对共享的和可变的状态访问。共享意味着变量可由多个线程同时访问,而可变意味着变量的值在器生命周期中可以发生变化。一个对象是否安全,取决于他书否被多个线程访问。当多个线程访问某个转台变量并且其中有一个线程是写入操作时,必须采用线程协同对变量进行访问。
1、什么是线程安全
当线程访问某个类时,这个类始终能够表现出正确的行为,那么就称这个类是线程安全的。无状态对象一定是线程安全的。大多数selvet都是无状态的,所从而极大地降低了在实现servlet线程安全时的复杂性。
2、原子性
当在无状态的对象中增加一个状态,如:在serlvet中增加一个计数器,用于记录访问的数量,这时候,变量不是原子性的:分为 读取-修改-写入 操作,并且其结果依赖于之前的状态,就会出现记录数值出现偏差,从而是不安全的。
2.1 竞态条件
在线程不安全中存在多个静态条件,从而使结果变得不可靠。最常见的竞态条件类型是:先检查后执行操作,通过一个可能失效的结果来决定下一步的动作。
延迟初始化中的竞态条件:如:放一个类中初始化某个类,而是初始化并返回这个类的方法中,首先判断这个了是否为null ,如果为null,则初始化返回,这时,如果并发线程A、B,B在进行获取时,取决于A获取类的时间以及线程的调度方式,就会出现不同的结果。
在上述问题中,可以采用线程安全的类来避免并发造成的线程不安全问题。能够保证所有对状态操作都是原子性的。
2.3 加锁机制
1.内置锁:同步代码块,分为两部分,一个作为锁的对象引用