1.为什么StringBuffer是线程安全的StringBuilder是线程不安全的



这里我只是列举了几个方法来对比,其他方法对比可以查看两个类的源码,从上面的截图可以看到StringBuffer实现线程安全是通过Synchronized字段来实现的,那么Synchronized的原理又是怎样实现的呢?下文将对此讨论。

2.Synchronized原理

2.1synchronized的三种应用方式
  • 修饰实例方法 对当前实例加锁
  • 修饰静态方法 对当前类对象加锁
  • 修饰代码块 对指定对象加锁

修饰实例方法

public synchronized StringBuffer append(int i) {toStringCache = null;super.append(i);return this;}

修饰静态方法

public static synchronized void test(){i++;}

修饰代码块

    public boolean contentEquals(CharSequence cs) {// Argument is a StringBuffer, StringBuildersynchronized(cs) {return nonSyncContentEquals((AbstractStringBuilder)cs);} }
2.2motitorenter、monitorexit指令

示例代码

public class Test
{public void test(String str) {synchronized (str) {System.out.println(str);}}
}

执行javac Test.java 生成Test.class文件
执行 javap -verbose -p Test.class,生成如下信息(只选取关键部分):

上面的字节码中包含一个 monitorenter 指令以及多个monitorexit指令,分别表示了JVM获取锁以及JVM解除锁。

  public synchronized void test2(String str) {System.out.println(str);}

执行 javap -verbose -p Test.class,生成如下信息(只选取关键部分):

当用 synchronized 标记方法时,这里会生成ACC_SYNCHRONIZED标记,这个标记表示在进入这个方法的时候JVM要进行motitorenter操作,当方法退出的时候,JVM 进行monitorexit操作。所以这里可以将ACC_SYNCHRONIZED标记理解为隐式的motitorenter、monitorexit操作。

2.3锁算法实现原理

在 Java 虚拟机中,每个 Java 对象都有一个对象头(object header),这个由标记字段和类型
指针所构成。其中,标记字段用以存储 Java 虚拟机有关该对象的运行数据,如哈希码、GC 信息
以及锁信息,而类型指针则指向该对象的类。

当JVM对对象加锁的时候,如果锁计数器为0,表示没有被任何线程持有,这时当前线程会持有该锁对象,会将锁计数器器加1,锁对象的持有该锁的线程指针会指向当前线程。如果锁对象的计数器不为0,如果持有该所对象的线程是当前线程,计数器加1,否则需要等待直到持有锁对象的线程释放该锁。
当JVM释放锁的时候会将计数减1,当计数器等于0,表示该锁被释放。

采取这种锁计数器方式,是考虑到同一线程重复获取锁的场景,举个例子一个类可能有多个方法被
synchronized 修饰,这些synchronized方法之间互相调用就是重复获取锁。

上面是对锁算法原理的描述,在HotSpot虚拟器中锁的具体实现主要涉及到以下几个概念:
重量级锁、轻量级锁、偏向锁,下面会逐一介绍这几个概念,在介绍前先看下下面这个表格(就是对象头里面的锁信息描述),结合这个表格理解会更加容易一些:


重量级锁
JVM会阻塞加锁失败的线程,当目标锁被释放的时候,再唤醒这些被阻塞的线程。阻塞线程、唤醒线程是一个比较重的操作,所以这正为什么被叫做“重量级锁”的原因。当然JVM也不是加锁失败就一味地阻塞唤醒,对此是有做优化的,JVM在线程进入阻塞之前和唤醒后任然竞争不到锁的时候,进入自旋状态——执行无用指令并且轮询锁是否放开,如果此时所释放线程能竞争到锁就无需进入阻塞状态了。当然自选会有一个副作用,那就是导致不公平,处于阻塞的线程没有办法立刻竞争释放的锁,自旋下的线程可能优先获得锁。

轻量级锁
多个线程在不同的时间段请求同一把锁,也就是说没有锁竞争。针对这种情形,Java 虚拟机采用了轻量级锁,来避免重量级锁的阻塞以及唤醒。

偏向锁
从始至终只有一个线程请求某一把锁

上面对几个概念做了介绍,那么线程在进行加锁,对象头信息又是如何变化的呢?
线程加锁的时,JVM会比较标记位最后两位是不是01(表示无锁或者偏向锁),如果时的话,则修改锁记录地址,最后两位被修改成00(表示轻量级锁),这时候线程已经持有该锁了。如果不是01结尾,则说明该锁已经被持有,可能时别的线程也可能时当前线程自己持有,如果是该线程重复获取同一把锁,则清空所记录,如果是其他线程持有锁,该锁会被膨胀成重量级锁,当前线程被阻塞。

StringBuffer、StringBuilder区别以及Synchronized原理相关推荐

  1. String StringBuffer StringBuilder区别与联系

    String     StringBuffer     StringBuilder String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量 ...

  2. string stringbuffer stringbuilder 区别

    共同点:String StringBufferStringBuilder 都是字符串相关函数,StringBuffer StringBuilder都是AbstractStringBuilder的子类 ...

  3. String,StringBuffer,StringBuilder区别

    String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全)  简 要的说, String 类型和 StringBuffer 类型的 ...

  4. Java学习之String StringBuffer StringBuilder区别

    1.String:对象长度是不可变的,是线程安全. 2.StringBuffer:对象长度是可变的,是线程安全. 3.StringBuilder:对象长度是可变,不是线程安全. 转载于:https:/ ...

  5. String、StringBuffer、StringBuilder区别

    无论是做Java或是Android,都避免不了遇到这个问题,其实开发过程中一般情况下是不会纠结,这个问题是面试必选经典题,今天有时间,就总结一下. String.StringBuffer.String ...

  6. String , StringBuffer 和 StringBuilder 区别

    转载:http://www.blogjava.net/chenpengyi/archive/2006/05/04/44492.html 相信大家对 String 和 StringBuffer 的区别也 ...

  7. String,StringBuffer和StringBuilder区别?

    String是字符串常量,final修饰;StringBuffer字符串变量(线程安全);StringBuilder 字符串变量(线程不安全).此外StringBuilder和StringBuffer ...

  8. 「每天一道面试题」String和StringBuilder、StringBuffer的区别

    Java提供了两种类型的字符串:不可变字符串和可变字符串,分别是String和StringBuffer/StringBuilder,其中String引用的字符串内容不能被改变,而StringBuffe ...

  9. String和StringBuilder、StringBuffer的区别?

    Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它们可以储存和操作字符串.其中String是只读字符串,也就意味着String引用的字符串内容是 ...

最新文章

  1. 机器学习(二)——鸢尾花案例
  2. docker环境搭建
  3. 如何创建圆角 UITextField 与内阴影
  4. 异步广度优先搜索算法
  5. c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理...
  6. linux借助expect完成自动登录
  7. mysql何时会走索引
  8. 矩池云上使用nohup和让任务后台运行
  9. Java从零开始(4)——入门项目
  10. 扎克伯格正用“山寨”策略碾压Snapchat
  11. SQL Server数据同步
  12. 计算机中丢失amtlib.dll如何办,amtlib.dll文件找不到怎么办-amtlib.dll文件找不到的解决办法...
  13. IOS13破解屏幕使用时间,无需电脑,不丢数据
  14. 汉诺塔(hanoi)
  15. VERSA VGG-4422-U-A120有一种幸福叫微笑
  16. JavaWeb 购物车项目
  17. elasticsearch 父子文档
  18. HCIP-IoT 芯片与模组
  19. hadoop 1.0 基本概念了解
  20. 多图养眼!Partition,荷兰国旗问题与随机快排

热门文章

  1. java frame paint_一个简单的java frame画图(paint)问题
  2. 获取图像的梯度,方向和方向梯度图像
  3. 判断奇偶microsoft visual basic_#梅园# 在心理学上面如何判断一个男生暗恋你的表现...
  4. 为了探究不同光照处理_浅谈中考物理实验探究易错题
  5. MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建
  6. GitLab 已迁移至谷歌云平台,并表示目前运行良好
  7. SharePoint Server 2007 Web内容管理中的几个关键概念
  8. 孰轻孰重:可穿戴式设备的助益与风险
  9. ServletContext 与application的异同
  10. iOS视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、view...