三个概念的理解:程序、进程和线程
程序:静态实体
进程:动态实体,存于内存,又叫任务,是程序的运行时期
线程:进程创建的更小粒度
编写线程安全的代码,本质上就是管理对状态的访问,而且通常都是共享的、可变的状态。所谓共享是指一个变量被多个线程访问;所谓可变是指变量的值在其生命周期内可以改变。
线程安全这个性质取决于程序中如何使用对象,而不是对象完成了什么。一开始就将类设计为线程安全的,比在后期修改他更容易。
一、概念
1、线程安全类:当多个线程访问一个类时,如果不用考虑线程在运行时的调度和交替执行,并且不用额外的同步机制作为协调,这个类的行为仍然是正确的,那么我们说这个类为线程安全的。
示例:无状态类——它不包含域也没有引用其他类的域。无状态对象永远是线程安全的。
解释:无状态对象只有一些方法,方法内部的局部变量会存到相应线程的堆栈中,每个线程的堆栈是独立的。
2、原子性:当其他线程想要访问查看或者修改一个状态时,必须在我们的线程开始之前或者完成之后,而不能在操作过程中。
原子操作:要么都执行,要么都不执行。
原子变量类:java.util.concurrent.atmoic里提供的原子变量类。类的小工具包,支持在单个变量上解除锁的线程安全编程。
3、java的内置的原子性机制——锁:synchronized块。块包含两部分:锁对象的引用,这个锁要保护的代码块。
3.1内部锁
3.2重进入
线程请求自己占有的锁时,请求会成功。
4、用锁来保护状态
操作共享状态的复合操作必须是原子操作。复合操作会在完整的运行期间占有锁,以确保其行为是原子的。
5、活跃度与性能
过于强调安全就会出现性能下降,过度强调安全,就会导致不必要的等待。
二、共享对象
1、可见性
为了确保跨线程写入内存的可见性,必须使用同步机制。只要数据需要跨线程共享,就进行恰当的同步。
1.1过期数据
没有进行恰当的线程同步机制,导致一个线程对共享数据的修改,并不能保证其余的线程是可见的。
1.2非原子的64位操作
java的存储模型要求存储和读取操作都为原子的,但是对于非volatile的long和double变量,JVM允许将64位的读或写划分为两个32位的操作。因此,在多线程中共享、可变的long和double变量也可能是不安全的,除非将他们声明为volatile类型,或者用锁保护起来。
1.3锁和可见性
锁不仅仅是关于同步和互斥的,也是关于内存可见性的。为了保证所有线程都能看到共享变量的最新值,读取和写入线程必须使用公共的锁进行同步。
1.4volatile变量
volatile相比锁而言,只是一种轻量级的同步机制。
volatile变量的典型应用:检查状态标记,以确定是否退出一个循环。
volatile也有缺点:volatile的语义并不能保证自增操作是原子操作。加锁可以保证原子性和可见性,volatile变量只能保证可见性。
2、线程封闭
2.1栈限制
栈限制是线程限制的一种特例,在栈限制中,只能通过本地变量才可以触及对象。每个线程都有自己的堆栈,本地变量基本上都存储与自己的堆栈,每个线程的堆栈是不会有冲突的,其他线程是不会访问到的,本地变量是线程封闭的。
2.2ThreadLoacl
一种维护线程限制的更加规范的形式,它允许将每个线程与持有数值的对象关联起来。ThreadLocal提供了get和set访问器,为每个使用他的线程维护一份单独的拷贝。其实和线程池差不多。
3、不可变性
不可变对象永远是线程安全的。不可变对象是简单的。
不可变对象的条件:
①他的状态不能再创建后修改(对“状态”的理解:对象的引用)
②所有的域都是final类型
使用volatile发布不可变对象:用不可变容器再加上volatile关键字发布不可变对象。具体代码如下

1 @immutable 2 public class OnerValueCache { 3 4 private final BigInteger lastNumBigInteger; 5 private final BigInteger [] lastFactorsBigIntegers; 6 7 public OnerValueCache(BigInteger num,BigInteger[] factors){ 8 lastNumBigInteger=num; 9 lastFactorsBigIntegers=Arrays.copyOf(factors,factors.length); 10 } 11 12 public BigInteger[] getFactors(BigInteger num){ 13 if(lastNumBigInteger==null||!lastNumBigInteger.equals(num)){ 14 return null; 15 } 16 return Arrays.copyOf(lastFactorsBigIntegers, lastFactorsBigIntegers.length); 17 } 18 }

1 @ThreadSafe 2 public class VolatileCachedFactorizer implements Servlet{ 3 private volatile OnerValueCache cache=new OnerValueCache(null,null); 4 public void service(){ 5 BigInteger i =extractFromRequest(req); 6 BigInteger Factors=cache.getFactors(i); 7 if(factors==null){ 8 factors=factor(i); 9 cache=new OnerValueCache(i,factors); 10 } 11 encodeIntResponse(resp,factors); 12 } 13 }