java 中为什么说,String是线程安全的

 我来答
_小小程序猿
2017-05-31 · TA获得超过115个赞
知道小有建树答主
回答量:74
采纳率:100%
帮助的人:17.9万
展开全部
  1. 首先我们谈谈线程安全.

    线程安全估计都是老生常谈了.

    例子:一个人的账户有银行卡和存折两个终端.共计5000元.当银行卡中取出2000的瞬间,服务器还没更新余额(此时应是3000),存折也向服务器发出取钱3000的请求,服务器查看余额剩余5000给予取款操作.此时存折出钞前,之前银行卡的余额更新到服务器.此时服务器余额为3000元,下个0.05秒存折出钞完毕,将余额更新到服务器,此时余额为2000元.



好了,取了5000元,共5000元最后卡里还剩2000.然后你就进去了.

2.线程安全的解决方案

(1)以上例子,最常用的解决方案就是使用同步语句块 synchronized来保护取款过程.当一个线程在访问该账号正在执行取款操作时,其他线程想要进行取款只能等待.这种方式是以时间换空间.

(2)使用ThreadLocal,ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。这种方式是以空间换时间.

好了,思维拓展结束.现在我们看问题,String为什么是线程安全的呢?

遍寻String的源码,你可能找不到几个synchronized关键字来.是的.我是在引导你走(2).

可是也没有看到ThreadLocal相关的东西啊.这是因为String在设计的时候字符的存储是放在char数组中的,而这个char数组是final的.也就是说,无论你是怎样的多线程环境.你做得修改操作

对原有的对象是没有任何影响的.因为String 在更改的时候是指向了另一个对象(也就是另一个char数组).每个线程修改的时候都是独立的一个char数组,这用的正是(2)方法.所以这个final的char数组才是String 安全的根本. 

还有StringBuffer和StringBuilder 两个都是放弃了使用final char数组.所以二者在拼接字符串的时候省内存(不用拼一个字符 new一个char数组了).但是这样就线程不安全了.这就是StringBuilder.而为什么stringBuilder是线程安全的呢.这是因为他的线程安全是用的(1)方法(大量的synchronized).

这里需要解释下,(2)方案为什么能解决线程安全问题.也可以理解为为什么用了final的char数组就可以实现线程安全.原理其实很简单.我们反过来想.线程不安全的情景,无非就是在对同一个对象同时修改的时候,其中一个线程只操作了一半,另一个线程也开始操作.因为线程的执行时间是cpu分配的时间片.并不是谁先执行就是谁先结束.完全有可能a线程先执行修改,在修改没完成的时候b线程也开始操作该对象.结果B线程先修改完毕.想象下.最终的结果可以肯定不是预期的结果.只有这种情况才会出现线程不安全.而当每个线程拥有一个实例的时候.这种情况将不复存在.

推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式