In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces the StringBuilder thread unsafe example analysis, the article is very detailed, has a certain reference value, interested friends must read it!
Introduction
Interviewer: what's the difference between StringBuilder and StringBuffer?
Me: StringBuilder is not thread-safe, StringBuffer is thread-safe
Interviewer: where is the point where StringBuilder is not safe?
Me:. (mute)
Before that, I only remembered the conclusion that StringBuilder is not thread-safe and StringBuffer is thread-safe. I never thought about why StringBuilder was not safe.
Analysis.
Before analyzing a problem, we need to know that the internal implementations of StringBuilder and StringBuffer, like the String class, store strings through an char array, except that the char array in the String class is final-modified and immutable, while the char array of StringBuilder and StringBuffer is mutable.
First of all, use a piece of code to see what happens when multithreading manipulates StringBuilder objects.
Public class StringBuilderDemo {public static void main (String [] args) throws InterruptedException {StringBuilder stringBuilder = new StringBuilder (); for (int I = 0; I
< 10; i++){ new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < 1000; j++){ stringBuilder.append("a"); } } }).start(); } Thread.sleep(100); System.out.println(stringBuilder.length()); }} 我们能看到这段代码创建了10个线程,每个线程循环1000次往StringBuilder对象里面append字符。正常情况下代码应该输出10000,但是实际运行会输出什么呢? 我们看到输出了"9326",小于预期的10000,并且还抛出了一个ArrayIndexOutOfBoundsException异常(异常不是必现)。 1、为什么输出值跟预期值不一样 我们先看一下StringBuilder的两个成员变量(这两个成员变量实际上是定义在AbstractStringBuilder里面的,StringBuilder和StringBuffer都继承了AbstractStringBuilder) //存储字符串的具体内容char[] value;//已经使用的字符数组的数量int count; 再看StringBuilder的append()方法: @Overridepublic StringBuilder append(String str) { super.append(str); return this;} StringBuilder的append()方法调用的父类AbstractStringBuilder的append()方法 1.public AbstractStringBuilder append(String str) {2. if (str == null)3. return appendNull();4. int len = str.length();5. ensureCapacityInternal(count + len);6. str.getChars(0, len, value, count);7. count += len;8. return this;9.} 我们先不管代码的第五行和第六行干了什么,直接看第七行,count += len不是一个原子操作。假设这个时候count值为10,len值为1,两个线程同时执行到了第七行,拿到的count值都是10,执行完加法运算后将结果赋值给count,所以两个线程执行完后count值为11,而不是12。这就是为什么测试代码输出的值要比10000小的原因。 2、为什么会抛出ArrayIndexOutOfBoundsException异常。 我们看回AbstractStringBuilder的append()方法源码的第五行,ensureCapacityInternal()方法是检查StringBuilder对象的原char数组的容量能不能盛下新的字符串,如果盛不下就调用expandCapacity()方法对char数组进行扩容。 private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length >0) expandCapacity (minimumCapacity);}
The logic of expansion is new a new char array, the new char array is twice the capacity of the original char array plus 2, and then copy the contents of the original array to the new array through the System.arryCopy () function, and finally point the pointer to the new char array.
Void expandCapacity (int minimumCapacity) {/ / calculate the new capacity int newCapacity = value.length * 2 + 2; / / omit some check logic. Value = Arrays.copyOf (value, newCapacity);}
Arrys.copyOf () method
Public static char [] copyOf (char [] original, int newLength) {char [] copy = new char [newLength]; / / copy array System.arraycopy (original, 0, copy, 0, Math.min (original.length, newLength)); return copy;}
The sixth line of the source code of the append () method of AbstractStringBuilder copies the contents of the char array in the String object into the char array of the StringBuilder object, as follows:
Str.getChars (0, len, value, count)
GetChars () method
Public void getChars (int srcBegin, int srcEnd, char dst [], int dstBegin) {/ / omitted some checks. System.arraycopy (value, srcBegin, dst, dstBegin, srcEnd-srcBegin);}
The copy process is shown in the following figure
Suppose there are now two threads executing the append () method of StringBuilder at the same time, and both threads have finished executing the ensureCapacityInternal () method on the fifth line, and now count=5.
At this point, thread 1 runs out of cpu time slices, and thread 2 continues to execute. After thread 2 finishes executing the entire append () method, count becomes 6.
Thread 1 gets a count value of 6 when it continues to execute the str.getChars () method on line 6, and throws an ArrayIndexOutOfBoundsException exception when it performs a copy of the char array.
At this point, the analysis of why StringBuilder is not safe has been completed. What will happen if we replace the StringBuilder object of the test code with the StringBuffer object?
The output is 10000, of course!
So what does StringBuffer do to ensure thread safety? You can know this problem by clicking into the append () method of StringBuffer.
The above is all the content of the article "sample Analysis of StringBuilder thread unsafe". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.