本文概念性的介绍和一些基本的多线程知识居多。
状态:一个对象的状态就是它的数据,存储在状态变量中。比如实例域或静态域。对象的状态还包括附属对象的域,比如HashMap的状态一部分存储到对象本身中,同时也存储到很多Map.Entry对象中。
共享:是指一个变量可以被多个线程访问。
可变:是指变量的值在其生命周期内可以改变。
任何时候,只要有多于一个线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用同步来协调对该变量的访问。
设计线程安全类时需要考虑三个因素:封装、不可变、明确的不变约束。
线程安全:当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必作其他的协调,这个类的行为仍然是正确的。(这只是其中一种描述,线程安全没有明确的定义)
原子性:原子性就是说一个操作不可以被中途cpu暂停然后调度, 即不能被中断, 要不就执行完, 要不就不执行。
复合操作:与原子操作相对。
竞争条件:当计算的正确性依赖于运行时相关的时序或者多线程交替时,会产生竞争条件。(比如check-then-act,lazyinitialization就是典型的竞争条件)
锁 内部锁:每个Java对象都可以隐式的扮演一个用于同步的锁的角色,这些内置的锁被称为内部锁或者监视器锁。内部锁在Java中扮演了互斥锁的角色,意味着最多只有一个线程可以拥有锁。
重进入:一个线程在请求其他线程占有的锁时,会被阻塞。然而线程在请求自己占有的锁时是不被阻塞的,也就是允许重进入。JVM是通过内部计数器实现重进入的。
每个共享的可变变量都需要由唯一的确定的锁保护。
对于每个涉及多个变量的不变约束,需要同一个锁保护其所有的变量。
活跃度:缩小同步的块可以提高活跃度。(性能不一定提高)
可见性:一个线程写入的值对另一个线程不一定是可见的。
公开化和逸出:不要让this在构造函数中逸出,如果逸出的话,this可能还未被完全构建,这会导致问题。这个就好比你让某人帮你去存钱,并告诉它存完钱之前不要告诉其他人,但是这个人自作主张,先把这件事告诉了其他人然后再存钱,这时就会有潜在的风险了。这里面还涉及到重排序的问题,包括其他像是volatile,final等详细讲解参考java内存模型。http://blog.csdn.net/cumtwyc/article/details/41513941