- 浏览: 62883 次
- 性别:
- 来自: 成都
文章分类
最新评论
今天看JDK String 源码有一段代码实在没想通,网上也没有什么资料,说说自己的理解。先贴上jdk这一段源码:
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
这是一个比较char序列的方法,但是这个方法为什么判断是stringbuff要加同步关键字,而StringBuilder却不加同步关键字,不是说StringBuffer才是同步的吗?要加这一段应该都加上。想不通,死活想不通,然后百度只有知乎上有一段回答:
因为“StringBuffer是线程安全的”是个非常不准确的命题——不谈场景无从谈起线程安全与否。
事实上题主贴出来的代码正是JDK为了维护StringBuffer在此场景中的“线程安全”的表象而做的保护。
这里的重点是:这是JDK的内部实现,所以有意为了速度而破坏了封装。String. nonSyncContentEquals()方法直接把AbstractStringBuilder的value字段指向的char[]拿了出来读取其内容。如果此时这是一个StringBuffer,而另一个线程正在对该StringBuffer的内容做修改,那么此处不锁住该StringBuffer实例的话,这个value数组里的内容就可能会并发的发生变化,这个方法就不可靠了。
所以,为了补偿破坏了的封装,这里就代劳StringBuffer的线程安全性,给它加上了锁。
链接:https://www.zhihu.com/question/41922604/answer/92956253
读这段回答还是没有明白为什么stringbuild不加关键字。我就连续读了5遍这段话。。。终于有点眉目了,说说自己的想法:
严格意义上来说,这里其实可以都不加关键字,在调用这个方法的时候才加上同步关键字,这样就可以保证同步问题,同时效率会更高。但是源码这样写的原因,就是保证了stringbuffer的那句话,stringbuffer是线程安全的,调用这个方法的时候,给人一种假象,只要传入的是stringbuffer的话,就是安全的。所以实际上整个方法是牺牲了速度来保障StringBuffer的安全。
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
这是一个比较char序列的方法,但是这个方法为什么判断是stringbuff要加同步关键字,而StringBuilder却不加同步关键字,不是说StringBuffer才是同步的吗?要加这一段应该都加上。想不通,死活想不通,然后百度只有知乎上有一段回答:
因为“StringBuffer是线程安全的”是个非常不准确的命题——不谈场景无从谈起线程安全与否。
事实上题主贴出来的代码正是JDK为了维护StringBuffer在此场景中的“线程安全”的表象而做的保护。
这里的重点是:这是JDK的内部实现,所以有意为了速度而破坏了封装。String. nonSyncContentEquals()方法直接把AbstractStringBuilder的value字段指向的char[]拿了出来读取其内容。如果此时这是一个StringBuffer,而另一个线程正在对该StringBuffer的内容做修改,那么此处不锁住该StringBuffer实例的话,这个value数组里的内容就可能会并发的发生变化,这个方法就不可靠了。
所以,为了补偿破坏了的封装,这里就代劳StringBuffer的线程安全性,给它加上了锁。
链接:https://www.zhihu.com/question/41922604/answer/92956253
读这段回答还是没有明白为什么stringbuild不加关键字。我就连续读了5遍这段话。。。终于有点眉目了,说说自己的想法:
严格意义上来说,这里其实可以都不加关键字,在调用这个方法的时候才加上同步关键字,这样就可以保证同步问题,同时效率会更高。但是源码这样写的原因,就是保证了stringbuffer的那句话,stringbuffer是线程安全的,调用这个方法的时候,给人一种假象,只要传入的是stringbuffer的话,就是安全的。所以实际上整个方法是牺牲了速度来保障StringBuffer的安全。
发表评论
-
读Objects源码
2018-06-17 14:02 333//该类是一个工具类,主要封装了对对象的equals,hash ... -
读java Optional 源码
2018-06-01 20:00 386//该类是jdk1.8新增的类,主要是为了解决NPE问题。 ... -
读AbstractStringBuilder源码
2017-10-16 16:56 351//该类是StringBuilder和StringBuff ... -
读String源码
2017-10-16 15:17 464//先看构造函数 public String() { ... -
java编译编码问题
2017-10-02 11:35 357最近由一个编码问题。让我对另一个编码问题产生了疑惑。 即我们在 ... -
在java服务端设置允许跨域请求
2017-08-29 10:58 2623//写一个filter对response进行过滤 pub ... -
java从数据库中查出来二次封装基于注解
2018-03-05 22:33 532实现类似于mybatis一对多关系和一对一关系: 上代码: ... -
java从数据库中查出来二次封装基于XML
2018-03-05 22:22 317实现类似于mybatis的配置关系一对多或者一对一的实现:基于 ... -
对abstract关键字的另一番理解
2017-03-22 16:10 261直接上代码: public abstract class An ... -
JVM垃圾回收历史
2017-02-17 16:30 324从网上看到一篇文章讲述垃圾回收的历史搬运过来: 为什么要有G ... -
java final关键字
2016-10-09 22:03 340final关键字的主要用于申明这个东西是不可变的。用于设计以及 ... -
java for each循环的原理
2016-10-09 21:18 456这篇介绍java for each原理的文章写的很棒,转过来m ... -
关于java内部类
2016-10-09 21:10 271关于java内部类,这篇文章写的非常好。尊重作者的劳动成果: ... -
java static关键字的作用
2016-10-05 17:23 259static关键字的设计初衷,套用thinking in ja ... -
关于反射泛型的封装
2016-09-11 16:16 430最近用到了jackson转json。看了下TypeRefere ... -
java到底是按照值传递还是引用传递
2016-07-25 19:45 396public class Transfer { pub ...
相关推荐
什么是不可变对象? 众所周知, 在Java中, String类是不可变的... 对于Java初学者, 对于String是不可变对象总是存有疑惑。看下面代码: String s = "ABCabc"; System.out.println("s = " + s); s = "1
java面试的疑惑剪辑 博文链接:https://z-jq1015.iteye.com/blog/248599
在IT领域,尤其是在软件开发中,C#是一种广泛使用的编程语言,尤其在Windows平台上。...社区、论坛、博客以及在线教程都能提供大量资源,帮助初学者解决疑惑。祝你在C#和注册表操作的学习旅程中取得成功!
这个方法需要三个参数:上下文(Context)、要显示的消息文本(String)和持续时间(int)。持续时间可以是`LENGTH_SHORT`或`LENGTH_LONG`,分别代表短时间和长时间显示。 ```java Toast.makeText(context, "Hello, ...
摘要:Java源码,Android源码,Android菜单 Android模仿的engadget TabBar菜单效果,有一个疑惑,咋实现当tab点击后,换一个Icon图呢?跟engadget的一样。 public void onTabChanged(String tabId)里无法实现,如果...
Android TAB菜单,仿engadget导航切换菜单效果,其实就是一个TAB,这个相信大家都比较熟悉了,在电脑上和Android、IOS系统中都很常见。。...在public void onTabChanged(String tabId)里无法实现。
这通常涉及到计时器(Timer)组件和字符串处理(String Handling)技术。 1. **创建编辑框和计时器对象**: 在易语言的界面上,首先需要添加一个编辑框组件和一个计时器组件。编辑框用于显示文本,计时器则用来...
name : string, // The file name. The path is not included. size : number, // The file size in bytes type : string, // The file type as reported by the client operating system creationdate :...
要理解这个问题,需要从源码的角度对其实现原理进行讲解。 首先,需要了解 Spring bean 的创建过程。 Spring 中的对象实例化是通过反射实现的,而对象的属性则是在对象实例化之后通过一定的方式设置的。这个过程...
1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是为什么? 15 1.29 为什么我的编译器不允许我定义大数组,如double array[256][256]? 15 命名空间 15 1.30 如何判断哪些标识符可以使用,...
1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是为什么? 1.29 为什么我的编译器不允许我定义大数组,如doublearray[256][256]? 命名空间 1.30如何判断哪些标识符可以使用,哪些被保留了...