线程安全的问题
当设计线程安全的类时,良好的面向对象技术、不可修改性,以及明晰的不可变性规范都能起到一定的帮助作用。
关于线程安全
线程安全就是当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步和协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。
可以在线程安全的类中安装同步机制,这样调用的时候就不需要相应的同步机制了。
另外无状态的对象一定是线程安全的。
原子性
竞态条件
发生静态条件的常见方式是先检查后执行,其实就是相互操作一个对象而已。比如延时实例化的例子
public Person getPerson() {
if(this.person==null) {
this.person = new Person();
}
return this.person;
}
还有类似的计数+1等等。
复合操作
这在操作系统中应该称为临界区。
原子类
在java.util.concurrent.atomic包中包含了一些原子变量类。这些类上的操作都是线程安全型的。
加锁机制
内置锁
synchronized (lock) {
...临界区
}
其他线程调用时会阻塞。
锁重入
如果一个线程访问一个另一个线程占用的锁,是不能通过的。但是一个线程访问它自己占用的锁是可以操作的。重入意味着锁操作的颗粒度是“线程”。
用锁保护状态
每个共享的可变变量都应该只由一个锁来保护,从而使维护人员知道是哪一个锁。通常将锁放入类的内部。
对于每个包含多个变量的不变性条件,其中涉及的所有变量都需要同一个锁来保护。
活跃性和性能
可使用缓存的策略。另外同步块范围太大也会影响并发,所以可以尽量减少同步块的范围。
在执行时间较长的代码块上,千万不要加上锁。