JVM学习(八):线程安全

1、线程安全:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也无需进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。

 

2、线程安全的等级(由强到弱依次如下):

(1)不可变:不可变(Immutable)对象一定是线程安全的。如用final修饰的基本数据类型、String枚举类以及java.lang.Number的部分子类(LongDouble等包装类,但AtomicInteger和AtomicLong并非不可变)。

(2)绝对线程安全:Java API中标注自己是线程安全的类,大多数都不是绝对线程安全。比如Vector容器,在同时做删除元素和获取元素的操作时,需要额外进行同步处理,才能真正做到线程安全。

(3)相对线程安全:即我们通常意义上所讲的线程安全,它需要保证对这个对象单独的操作是线程安全的,但对于一些特定顺序的连续调用,需要使用额外的同步措施才能保证调用结果的正确性。Java中比如Vector、HashTable、Collections的synchronizedCollection()方法包装的集合等都属于相对线程安全。

(4)线程兼容:对象本身不是线程安全,需要额外的同步手段来保证并发执行的安全,比如ArrayList和HashMap等集合类。

(5)线程对立:线程不安全,无论如何都不能在并发环境下保证线程安全的情况,很少出现,应尽量避免。比如已经废弃的中断线程的suspend()方法和恢复线程的resume()方法。

 

3、线程安全的实现方法:

(1)互斥同步:基于悲观并发策略实现的阻塞同步,同步是指在多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个(或一些,使用信号量的时候)线程使用。临界区互斥量信号量都是主要的互斥实现方式,互斥是方法,同步是目的。Java中实现互斥同步的手段有使用synchronized关键字和使用J.U.C包中的重入锁(ReentrantLock)等。

(2)非阻塞同步:基于冲突检测的乐观并发策略,先对共享数据进行操作,如果发现没有竞争则操作成功,有就采取补偿措施(通常就是不断的重试,直至成功),操作和冲突检测必须具备原子性,需要硬件指令集的支持,比如CAS指令

(3)无同步方案:不涉及共享数据,则无需同步,本身就支持线程安全,比如可重入代码或者线程本地存储(ThreadLocal)。

posted on 2019-08-25 10:39  逍遥1989  阅读(199)  评论(0编辑  收藏  举报