你还以为StringBuffer是线程安全? 面试问到再也别说一定安全了!!!

      你还以为StringBuffer是线程安全?面试问到再也别说一定安全了。

每一个学过java的小伙伴都会背,StringBuffer是线程安全的,StringBuilder是非线程安全的;Hashtable是线程安全的,HashMap是非线程安全的。把这几条当成公理在用了,我面试的同学中,不管能力好坏,这几句都能背出来。

我们看一下StringBuffer的官方注释:

StringBuffer is A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls. String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.

就连官方的注释上也写着,StringBuffer是一个线程安全的可变的字符序列。StringBuffer可以安全的在多线程场景下使用。

事实真的是这样的吗?还真不是。StringBuffer既不是线程安全的,而且是一点卵用没有,任何出现StringBuffer的地方都可以用StringBuilder去替换。

				为什么StringBuffer不是线程安全的

首先咱们得定义什么是线程安全,线程安全就是在多线程运行的环境下,最终输出结果是正确的。其实任何一个类,即便它的所有方法都是synchonized,你也不能无中生有、暗度陈仓、凭空想象、胡作非为。

通常我们用的比较多的是append、insert、substring这些方法。你好好想一下,这些方法如果在多线程环境运行的情况下,它能保证程序运行结果的正确性和一致性吗?

•append为例
•从参加工作到现在,我遇到的所有append,拼接sql是多较多的,或者是把数据库中的几个字段拼接成一段话。
•如果是多线程环境运行,你根本无法预测最终结果是什么,不光是你预测不了,JVM自己都不知道最终出来的是个什么货,只能交给天意了
•以insert为例
•如果你要insert, 你需要知道自己是要insert到哪一个位置,比如在第一个出现的媳妇前插入一句我爱你三个字,那你写代码的话就是两行代码

int index = stringBuffer.indexOf(“媳妇”);
 if(index >= 0){
    
    
 stringBuffer.insert(index,“我爱你”);
 }

同志们,发现啥问题没,你要完成这个功能需要三步操作,当你完成第一步操作算出index是多少的时候,这时候很可能出现一个不怀好意的第三者线程从中作梗,最后你发现输出的结果根本不是那么回事。如果你想要这个功能好使,你还是得自己弄把锁,把刚才的方法锁住,确保你的操作是原子性的,其他要操作这个stringBuffer的地方,得拿到这把锁才行。

说了这么多,你发现了没,你找不到一个用StringBuffer的理由,我工作这么久是没见过,不光我没见过,Effective java的作者josh bloch也说没见过,他在书中说:

StringBuffer instances are almost always used by a single thread, yet they perform internal synchronization. It is for this reason that StringBuffer was supplanted by StringBuilder, which is just an unsynchronized StringBuffer.

			既然无用,那就让我们来消灭StringBuffer吧

java 5.0在2006年发布时,提供了StringBuilder这个类,到现在14年已经过去了。这个StringBuffer还有屹立不倒的出现在各种代码中。就连java的源码中,也到处充斥着无用的StringBuffer。

终于在2014年的某一天,一名叫Paul Sandoz的人实在受不了了,于是给openjdk提了个issue,说咱能不能把java内部核心库中用到StringBuffer的地方替换为StringBuilder

猜你喜欢

转载自blog.csdn.net/fewefgds/article/details/108378034
今日推荐