什么是线程安全,你真的了解吗?
The following article is from 一个程序员的成长 Author 一个程序员的成长
来源:一个程序员的成长
公众号注:Java学习网站,点击文末阅读原文直达
记得今年3月份刚来杭州面试的时候,有一家公司的技术总监问了我这样一个问题,说你给我说说有哪些线程安全的类,我心里一想,呵呵,这我早都背好了,稀里哗啦说了一大堆,那你再来说说什么是线程安全,然后就GG了,说真的,我们整天说线程安全,但是你对什么是线程安全真的了解嘛?说真的,我之前真的是了解甚微,那么我们今天就来聊聊这个问题。
再说什么是线程安全之前我们先来聊聊什么是进程。
先来看一张图
我们看到的这些单独运行的程序就是一个独立的进程,进程之间是相互独立存在的。
我们上面图中的QQ、酷狗播放器、电脑管家等等都是独立的进程。
上面简单的说了一下什么是进程,进程想要执行任务需要依赖线程,换句话说就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。
提到多线程这里要说两个概念,就是串行和并行,搞清楚这个我们才能更好的理解多线程。
所谓串行其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子,我们下载多个文件,在串行中它是按照一定的顺序去进行下载的,也就是说必须等下载完A之后,才能开始下载B,它们在时间上是不可能发生重叠的。
并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的在同一时刻发生的,并行在时间上是重叠的。
了解了这两个概念之后我们再来说说什么是多线程,举个例子,我们打开腾讯关键,腾讯关键本身就是一个程序也就是说它就是一个进程,它里面有很多的功能,我们可以看下图,能查杀病毒、清理垃圾、电脑加速等众多功能,按照单线程来说,你想要清理垃圾还要病毒查杀,那么你必须先做完其中的一件事才能做下一件事,是有一个执行的顺序的,如果是多线程的话,我们其实在清理垃圾的时候还可以查杀病毒、电脑加速等等其他的操作,这个是严格意义上的同一时刻发生的,没有执行的先后顺序。
一句话总结一下:一个进程运行时产生了多个线程。
在了解完这个问题后,我们又需要去了解一个使用多线程不得不考虑的问题,线程安全,今天我们不说如何保证一个线程的安全,我们聊聊什么是线程安全?因为我之前面试被问到了,说真的,我之前真的不是特别了解这个问题,我们好像只学如何确保一个线程安全,却不知道所谓的安全到底是什么!
既然是线程安全问题,那么毫无疑问所有的隐患都是出现在多个线程访问的情况下产生的,也就是我们要确保在多条线程访问的时候,我们的程序还能按照我们预期的行为去执行,我们看一下下面的代码。
Integer count = 0;
public void getCount() {
count ++;
System.out.println(count);
}
很简单的一段代码,我们就来统计一下这个方法的访问次数,多个线程同时访问会不会出现什么问题,我开启的3条线程每个线程循环10次,得到一下结果
我们可以看到,这里出现了两个26,为什么会出现这种情况,出现这种情况显然表明我们这个方法根本就不是线程安全的,出现这种问题的原因有很多,我们说最常见的一种,就是我们A线程在进入方法后,拿到了count的值,刚把这个值读取出来还没有改变count的值的时候,结果线程B也进来的,那么导致线程A和线程B拿到的count值是一样的。
那么由此我们可以了解这确实不是一个线程安全的类,因为他们都需要操作这个共享的变量,其实要对线程安全问题给出一个明确的定义还是蛮复杂的,我们根据我们这个程序来总结下什么是线程安全。
当多个线程访问某个方法时,不管你通过怎样的调用方式或者说这些线程如何交替的执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类时线程安全的。
PS:那么你知道有哪些方法可以保证线程安全吗?
看完本文有收获?请转发分享给更多人