### Java并发编程实践笔记知识点详解
#### 一、保证线程安全的方法
1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。因此,避免直接在多个线程间共享变量,可以通过传递参数等方式来替代。
2. **使共享变量是final类型的:** 使用`final`修饰符可以确保一旦变量被初始化后就不可改变。这样即使在多线程环境中,也不会有线程试图修改这个变量,从而保证线程安全。
3. **将共享变量的操作加上同步:** 对于确实需要在线程间共享的变量,可以通过`synchronized`关键字或其他锁机制来确保同一时刻只有一个线程可以访问该变量。
#### 二、设计线程安全类的最佳实践
1. **一开始就设计为线程安全:** 在类的设计阶段就考虑线程安全问题,比后续修复要容易得多。
2. **确保正确性优先于性能:** 多线程编程中,首先确保程序逻辑的正确性,然后再考虑如何优化性能。
3. **无状态或只读对象是线程安全的:** 如果一个对象不包含任何状态信息(即无状态)或其状态不会改变(只读),那么它可以安全地被多个线程共享。
4. **保护共享变量:** 避免在没有适当同步措施的情况下让多个线程访问同一个变量。
5. **延迟加载的同步保护:** 如果一个对象需要在运行时动态创建,确保在第一次加载时采取同步措施,避免多次实例化。
6. **Volatile变量的问题:** `volatile`关键字可以保证变量的可见性,但不能保证原子性。在进行数值运算时尤其需要注意这一点,因为编译器或处理器可能会对其进行重排序。
7. **可重入锁的应用:** 可重入锁允许同一线程多次获取同一把锁,这对于处理递归调用等场景非常有用。Java提供了`ReentrantLock`类来实现这一特性。
8. **每个共享变量的唯一锁:** 为了保证数据一致性,每个共享变量都应该有一个唯一的锁来保护它。这可以通过创建多个`ReentrantLock`实例来实现。
9. **避免拆分原子操作:** 即使是为了提升性能,也不应将原本应在一个同步块内的操作拆分成多个同步块,这样可能会导致数据不一致。
10. **指令重排序的影响:** 编译器和处理器可能会为了优化性能而改变指令的执行顺序,这可能会导致线程安全问题。
11. **最低限的安全性:** 即使没有同步,读取未同步变量的线程至少能看到之前写入的值。这是一种最低限的安全性保证,但对于数值运算并不适用。
12. **Volatile变量的局限性:** `volatile`变量只能确保可见性,不能保证原子性。
13. **避免在持有锁时执行长时间操作:** 对于耗时较长的操作(如网络或I/O操作),不应在持有锁的情况下执行,以免阻塞其他线程。
14. **对象发布的注意事项:** 发布对象时必须确保其完全构造完成,以防止对象逸出导致的线程安全问题。
15. **使用ThreadLocal确保线程封闭性:** 通过`ThreadLocal`可以在每个线程中存储独立的副本,从而避免线程间的数据竞争。
16. **单一不可变对象的优势:** 不可变对象在多线程环境中是线程安全的,应尽可能使用不可变对象,并确保所有成员变量都是不可变的。
17. **安全发布共享变量:** 确保共享变量在被多个线程访问之前已经被安全地初始化和发布。
18. **设计线程安全类的基本要素:**
- 明确哪些变量是可变且需要共享的。
- 明确哪些变量是不可变的。
- 指定管理并发访问的策略。
19. **数据封装与原子性:** 将数据封装在对象内部,并确保对数据的访问是原子性的。可以使用`volatile`字段或同步的getter/setter方法来实现。
20. **线程限制性的优点:** 通过限制类的状态,可以简化线程安全性的分析。
21. **充分的文档说明:** 并发程序需要更详尽的注释和文档,以便于理解和维护。
22. **使用外部对象作为监视器:** 在需要细分锁分配时,使用外部对象作为监视器锁,相比于使用`this`作为锁提供更好的灵活性。
23. **委托给线程安全的类:** 在设计并发程序时,考虑将共享变量委托给已有的线程安全类来管理。
24. **同步容器的迭代器问题:** 使用传统的同步容器(如`Vector`和`Hashtable`)时,其迭代器是非线程安全的,需要额外的同步措施来保证正确性。
25. **使用并发容器:** 在并发编程中,推荐使用JDK提供的并发容器(如`ConcurrentHashMap`, `ConcurrentLinkedQueue`等),这些容器已经实现了线程安全机制,可以直接用于多线程环境。
以上是Java并发编程实践笔记中总结的关键知识点,涵盖了从基本概念到高级技术的应用,旨在帮助开发者构建高效、可靠的多线程应用。