Java线程: 第二章 多线程编程的目标与挑战(一)
2.1 串行、并发与并行
串行:ABC
并发:A
B
C
并行:A
B
C
2.2 竞态
2.2.1
竞态是指计算的正确性依赖于时间顺序或者线程的交错。
竞态往往伴随着Dirty Read问题,即线程读取到一个过时的数据,Lost Update问题,即一个线程对数据所做的更新没有体现在后续对其他数据的读取上。
2.2.2 竞态的模式与竞态产生的条件
竞态模式:read-modify-wirte(读-改-写),check-then-act(检查而后行动)。
使用synchronize关键字规避竞态:
public class A{ private short sequence = -1; public synchronized short nextSequence(){ if(sequeue >= 999) sequeue = 0; else sequeue++; return sequeue; } }
synchronize关键字使其修饰的方法在任一时刻只能被一个线程执行。
2.3 线程安全性
线程的安全问题概括来说包括3个方面:原子性,可见性,有序性。
2.4 原子性
原子操作是多线程环境下的一个概念,它是针对访问共享变量的操作而言的。原子操作的“不可分割”包括以下两层含义:
(1)读、写某个共享变量的操作从其执行线程以外的线程来看,该操作要么已经执行结束,要么尚未发生,即其他线程不会“看到”该操作执行了部分的中间结果。
(2)访问同一组共享变量的原子操作是不能够被交错的。
实现原子性的方法:
(1)利用Lock。
(2)利用处理器提供专门的CAS(Compare-and-Swap)。
Java中,long和double以外的任何变量的写操作都是原子操作,但是Java规定对于volatile修饰的long/double型变量的写操作具有原子性。
然而,volatile只能保证变量写操作的原子性,并不能保障其他操作的原子性。