Javaのコレクションシリーズファイブ:StringBuilderの理由はスレッドセーフではありませんか?

入門

実際のStringBuilderがセットに属していないが、内側に書かれた記事のないオープン新連載のために、このシリーズ。私たちは、面接の過程にある、インタビュアーは時々、このようなHashMapの関連の問題などなど着実なJavaベースの問題を指しています。我々は、すべてのStringBuilderはスレッドセーフではないことを知っているので、インタビュープロセス場合、インタビュアーは、それがスレッドセーフでない理由を尋ねるし続け、多くの人々がこの問題に立ち往生しています。

  • ソースコード解析
  • 概要

まず、ソースコード解析

図1に示すように、追記解析方法
を以下に示し、StringBuilderそしてStringBuffer以下のようにソースコードは、彼らが受け継いでいますAbstractStringBuilder

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
...
}
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
...
}

次のように使用する親クラスのメンバ変数は以下のとおりです。

//存储字符串的数据
char[] value;
//已经使用的字符数组数量
int count;

私はそれを使用するStringBuilderだけでなく、StringBuffer最も一般的に使用されappend、以下のように、方法:

//可以追加任意对象
@Override
public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }
//可以追加字符串
@Override
public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

実際には親クラスの呼び出し、AbstractStringBuilderappendメソッドを。次のとおりです。

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        //变量数据更新
        count += len;
        return this;
    }

上記のコードから分かるように、count += len;アトミック操作ではありません。このカウント値で、例えば10であり、LEN同時に後者の二つのスレッドの実装にカウント値は、カウントに加えの割当結果を実行した後、10であり得るため、7行目を実行するために1、二つのスレッドであります代わりに、12の11のカウント値、。だから、StringBuilderスレッドセーフです。

2、分析のappendメソッド
、我々は戻って見て、5行目のソースアプローチがチェックすることです元のオブジェクトあなたがオーバーフローを呼び出す場合は、アレイの容量を、新しい文字列を保持することはできませんする方法アレイの拡張を。AbstractStringBuilderappend()ensureCapacityInternal()StringBuildercharArrays.copyOfchar

 private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
 public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

第二に、要約

そのアトミック操作を保証するために該当する同期動作がないため、いくつかのスレッド安全でない動作は、実際には、JDKのソースコードが存在します。だから我々は、このことにより、分析することができ、かつ適切に最適化し、改善することができます。

88元記事公開 ウォン称賛49 ビューに10万+を

おすすめ

転載: blog.csdn.net/Diamond_Tao/article/details/102129598