java并发编程实战笔记---(第二章)线程安全:正确性 (第二章)线程安全:正确性 2.1原子性
ThreadA__________ 同步 ______________
异步 ___________ 异步
ThreadB__________ ______________
后台进程 : 程序结束 ,则后台进程随之结束。
多个线程都可能访问,有共享,就要考虑线程安全。
Timer : 开启新线程, timerTask 如果访问程序中的数据,那么该数据的访问需要是线程安全的,简单方法:将线程安全封装在共享数据内部。timer:AtFixed是从上次开始时间算起。不加 AtFixed,若执行时间更长,则是从上次结束时间算起。
Servlet 是单例的,可能被多个线程调用,servlet是共享数据,本身需要线程安全。
线程安全类中封装了必要的同步机制,因此客户端无须进一步采取同步措施。
局部变量存在于线程栈,只有执行线程可以访问,状态对象存在于堆中,线程之间可以共享。
线程安全性:多个线程之间的操作无论采用何种执行时序或交替方式,都要保证不变性条件不被破坏。
无状态: 自身不包含域,也不包含对其他类中域的引用。
无状态对象是线程安全的。
2.1原子性
竞态条件:操作时序会影响结果的正确性。
1. 读取--修改--写入
有状态:count
++count : 1.获取count 2.count+1 3.赋值给count
2.先检查后执行 :延迟初始化
3.使用现有的线程安全类:AtomicLong 确保操作的原子性
4. 但是若有多个状态值,尽管是线程安全类,结果也并不一定正确。
要保证状态的一致性,就要在单个原子操作中更新所有相关的状态变量。
2.3加锁机制
1.内置锁
synchronized 同步方法锁:当前对象,静态同步方法 锁:当前类。
同步代码块互斥,只有一个线程可以访问,但是性能就可能低。
2.重入
内置锁是可以重入的。重入意味获取锁的粒度是“线程”,而不是“调用”。
重入的一种实现方法是,为每个锁关联一个获取 计数值和一个所有者线程。
内置锁重入避免了以下线程的死锁。
2.4活跃性和性能
合理处理加锁代码块。
当执行时间较长的计算或者无法快速完成的 操作时(网络io,控制台io),千万不要持有锁。