【线程安全问题无大小:Java中的线程安全之操作共享数据分类】线程安全这个名称,相信稍有经验的程序员都会听说过,甚至在代码编写和走查的时候可能还会经常挂在嘴边,并且在面试中是问的最多的,但凡有处理线程安全问题经验丰富的程序员,都会很吃香 。线程安全怎么来定义呢?一本书中曾做过定义:“当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的” 。
今天就来说一说JAVA语言中的线程安全,线程安全问题,无非就是对共享数据的处理,在Java语言中,处理共享数据可以分为:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立 。
一、不可变
在Java语言中,不可变 (Immutable)的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再采取任何的线程安全保障措施,只要一个不可变的对象被正确地构建出来,那 其外部的可见状态永远也不会改变,永远也不会看到它在多个线程之中处于不一致的状态 。“不可变”带来的安全性是最简单和最纯粹的 。如果共享数据是一个基本数据类型,那么只要在定义时使用final关键字修 饰它就可以保证它是不可变的 。如果共享数据是一个对象,那就需要保证对象的行为不会对 其状态产生任何影响才行,大家都熟悉java.lang.String类的对象,它是一个典型的不可变对象,我们调用它的substring()、replace()和concat()这些方法都不会影响它原来的值,只会返回一个新构造的字符串对象 。
文章插图
保证对象行为不影响自己状态的途径有很多种,其中最简单的就是把对象中带有状态的变量都声明为final,这样在构造函数结束之后,它就是不可变的,比如java.lang.Integer的构造函数,它通过将内部状态变量value定义为final来保障状态不变 。
文章插图
二、绝对线程安全
绝对的线程安全就是要完全满足:一个类要达到“不管运行时环境如何,调用者都不需要任何额外的同步措施”通常需要付出很大的,甚至有时候是不切实际的代价 。在Java API中标注自己是线程安全的类,大多数都不是绝对的线程安全 。java.util.Vector是一个线程安全的容器,因为它的add()、get()和size()这类方法都是被synchronized修饰的,尽管这样效率很低,但确实是安全的 。但是,即使它所有的方法都被修饰成同步,也不意味着调用它的时候永远都不再需要同步手段了 。
文章插图
假如我们在另外一个A方法中调用Vector类中的线程安全的方法,如果 A方法不加synchronized关键字,这个A方法也是线程非安全的 。
三、相对线程安全
相对的线程安全就是我们通常意义上所讲的线程安全,它需要保证对这个对象单独的操作是线程安全的,我们在调用的时候不需要做额外的保障措施,但是对于一些特定顺序的连 续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性 。在Java语言中,大部分的线程安全类都属于这种类型,例如Vector、HashTable、Collections的synchronizedCollection()方法包装的集合等 。
四、线程兼容
线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全地使用,我们平常说一个类不是线程安全的,绝大多数时候指的是这一种情况 。Java API中大部分的类都是属于线程兼容的,如与前面的Vector和HashTable相对应的集合类ArrayList和HashMap等 。
五、线程对立
线程对立是指无论调用端是否采取了同步措施,都无法在多线程环境中并发使用的代码 。由于Java语言天生就具备多线程特性,线程对立这种排斥多线程的代码是很少出现的,而且通常都是有害的,应当尽量避免 。一个线程对立的例子是Thread类的suspend()和resume()方法,如果有两个线程同时持有一个线程对象,一个尝试去中断线程,另一个尝试去恢复线程,如果并发进行的话,无论调用时是否进行了同步,目标线程都是存在死锁风险的,如果suspend()中断的线程就是即将要执行resume()的那个线程,那就肯定要产生死锁了 。也正是由于这个原因,suspend()和resume()方法已经被JDK声明废(@Deprecated)了 。常见的线程对立的操作还有System.setIn()、Sytem.setOut()和
推荐阅读
- 舌头发白是什么原因
- 明朝争国本事件,关于明朝的问题
- 安全研究人员开发出可在检测到破解时自毁数据的Android应用
- C++实现线程池
- 看空调摆放需要注意的4大问题 谈空调摆放的窍门
- 人工智能在网络安全领域中的应用场景
- 2021年校招程序员之阿里四个部门的十轮面试问题
- 一 OAuth网络安全登录认证
- 三 OAuth网络安全登录认证
- 微软开放AI安全风险评估工具Counterfit源代码