线程安全策略
2018-12-01 本文已影响2人
达小谢
策略1 - 不可变对象
- 对象创建以后其状态就不能修改。
- 对象所有域都是final类型。
- 对象是正确创建的(在对象创建期间,this引用没有逸出)。
final关键字:类、方法、变量
- final类:不能被继承。
- 修饰方法:锁定方法不被继承类修改。
- 修饰变量:基本数据类型变量(值不能变更),引用类型变量(不能再指向其它对象)。
@Slf4j
@ThreadSafe
public class ImmutableExample2 {
private static Map<Integer, Integer> map = Maps.newHashMap();
static {
map.put(1, 2);
map.put(3, 4);
map.put(5, 6);
map = Collections.unmodifiableMap(map);
}
public static void main(String[] args) {
map.put(1, 3);
log.info("{}", map.get(1));
}
}
Guava提供了许多不可变的集合
@ThreadSafe
public class ImmutableExample3 {
private final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);
private final static ImmutableSet set = ImmutableSet.copyOf(list);
private final static ImmutableMap<Integer, Integer> map = ImmutableMap.of(1, 2, 3, 4);
private final static ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder()
.put(1, 2).put(3, 4).put(5, 6).build();
public static void main(String[] args) {
System.out.println(map2.get(3));
}
}
策略2 - 线程封闭
仅在单线程内访问数据,不需要同步
2.1 Ad-hoc线程封闭
指维护线程封闭性的职责完全由程序实现来承担。Ad-hoc线程封闭是非常脆弱的,因为没有任何一种语言特性,例如可见性修饰符或局部变量,能将对象封闭到目标线程上。
当决定使用线程封闭技术时,通常是因为要将某个特定的子系统实现为一个单线程子系统。程序控制实现,最糟糕,忽略
。
2.2 堆栈封闭
在栈封闭中,只能通过局部变量才能访问对象。栈封闭(也被称为线程内部使用或者线程局部使用)比Ad-hoc线程封闭更易于维护,也更加健壮。
2.3 ThreadLocal线程封闭:特别好的方法
策略3 - JUC工具包
- 以Concurrent前缀的并发类,如ConcurrentHashMap
- 含有Blocking的阻塞类,如LinkedBlockingDeque
- 以Atomic为前缀的原子变量类,如AtomicInteger
-辅助工具类,如CountDownLatch
策略4 - 无状态
- 没有实例域
- 如Servlet
策略5 - 同步锁
- synchronized
- ReentrantLock
- ReentrantReadWriteLock