面试问到线程怎么回答(连线程不安全都说不出个所以然)
分享职场干货、软件编程、程序人生和创业资源。
文|洪生鹏 编辑|静子
程序员面试时,线程安全知识点经常会遇到。
小洪是一名java程序员,工作两年多了,最近去了某互联网公司面试,面试时,面试官问了这样一个问题:
面试官:StringBuilder和StringBuffer有什么区别?
小洪:StringBuilder线程不安全的,StringBuffer是线程安全的
面试官:能举个例子说说StringBuilder是怎么线程不安全的吗?
小洪:……
小洪有点懵了,平时在用在使用StringBuilder追加字符时,只是简单的用,只知道它是不是线程安全,至于不安全在哪里,小洪并没有去关注。
见小洪没有作答,面谈时面试官又问,StringBuffer哪里安全了,小洪也回答不出个所以然。
面试官:你都工作两年了,这个都不知道,怎么写出稳定的程序啊?小洪一脸的无助,不过确实不应该,类似StringBuilder常见的知识点,平时应该不会少用,应该掌握才对。
刚毕业的时候,面试时也遇到了类似关于StringBuild的问题,关于StringBuild线程不安全简单来说StringBuilder没有加锁,而StringBuffer有加锁。面试时,这样回答固然没有错,但要是能进一步分析个所以然那就更好了,相信能给面试官留下更好的印象。
我们举个例子来验证下
1. 分别用500个线程写StringBuffer和StringBuilder,
2. 保证在各自500个线程执行完后打印StringBuffer和StringBuilder字符串长度
3. 检验运行结果。
测试
线程不安全测试
我们创建了500个线程,每个线程往StringBuilder对象里面append一个字符p。正常情况下代码应该输出500,但是实际运行结果是什么呢?
测试结果我们看到字符串长度有时候是496,有时候是498,小于预期值500。而当我们把StringBuilder换成StringBuffer不管运行多少次,结果的值都是500,从这个例子我们可以得出StringBuffer线程安全,StringBuilder线程不安全得到了证明。
为什么输出值跟预期值不一样,源码分析为什么会小于期望值,我们来看下StringBuilder的源码
StringBuilder的append()方法调用的父类AbstractStringBuilder的append()方法,我们来看下这个方法具体做了什么。
源码分析
细心的你会发现count = len;这一行代码并不是一个原子操作。
假设count的值为10,len值为1,这时候有两个线程同时执行到了这行代码,count值都是10,执行完后将结果赋值给count,这两个线程执行完后count值为11,而不是12。这就是为什么测试代码输出的值要小于我们的期望值500的原因了。
而当我们换成StringBuffer类是,为什么能保证输出的是500,我们看一下StringBuffer源码就会发现所有写操作都有synchronized修饰了
而StringBuilder的写操作则没有使用synchronized进行修饰。
StringBuilder类的append方法
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
StringBuffer 类的append方法
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
关于StringBuilder不是线程安全的例子就分析到这。笔者觉得类似这样的基础知识点需要在平时学习中不断摸索,不断去探索实践,不断运用,才能在工作中更好地解决问题。由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,敬请读者不吝赐教,是为至盼。
,
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。