面试问到线程怎么回答(连线程不安全都说不出个所以然)

分享职场干货、软件编程、程序人生和创业资源。

文|洪生鹏 编辑|静子

程序员面试时,线程安全知识点经常会遇到。

小洪是一名java程序员,工作两年多了,最近去了某互联网公司面试,面试时,面试官问了这样一个问题:

面试官:StringBuilder和StringBuffer有什么区别?

小洪:StringBuilder线程不安全的,StringBuffer是线程安全的

面试官:能举个例子说说StringBuilder是怎么线程不安全的吗?

小洪:……

小洪有点懵了,平时在用在使用StringBuilder追加字符时,只是简单的用,只知道它是不是线程安全,至于不安全在哪里,小洪并没有去关注。

见小洪没有作答,面谈时面试官又问,StringBuffer哪里安全了,小洪也回答不出个所以然。

面试官:你都工作两年了,这个都不知道,怎么写出稳定的程序啊?小洪一脸的无助,不过确实不应该,类似StringBuilder常见的知识点,平时应该不会少用,应该掌握才对。

刚毕业的时候,面试时也遇到了类似关于StringBuild的问题,关于StringBuild线程不安全简单来说StringBuilder没有加锁,而StringBuffer有加锁。面试时,这样回答固然没有错,但要是能进一步分析个所以然那就更好了,相信能给面试官留下更好的印象。

我们举个例子来验证下

1. 分别用500个线程写StringBuffer和StringBuilder,

2. 保证在各自500个线程执行完后打印StringBuffer和StringBuilder字符串长度

3. 检验运行结果。

测试

面试问到线程怎么回答(连线程不安全都说不出个所以然)(1)

线程不安全测试

我们创建了500个线程,每个线程往StringBuilder对象里面append一个字符p。正常情况下代码应该输出500,但是实际运行结果是什么呢?

测试结果

我们看到字符串长度有时候是496,有时候是498,小于预期值500。而当我们把StringBuilder换成StringBuffer不管运行多少次,结果的值都是500,从这个例子我们可以得出StringBuffer线程安全,StringBuilder线程不安全得到了证明。

为什么输出值跟预期值不一样,源码分析

为什么会小于期望值,我们来看下StringBuilder的源码

StringBuilder的append()方法调用的父类AbstractStringBuilder的append()方法,我们来看下这个方法具体做了什么。

面试问到线程怎么回答(连线程不安全都说不出个所以然)(2)

源码分析

细心的你会发现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不是线程安全的例子就分析到这。笔者觉得类似这样的基础知识点需要在平时学习中不断摸索,不断去探索实践,不断运用,才能在工作中更好地解决问题。由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,敬请读者不吝赐教,是为至盼。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。