1

スレッドセーフの観点から、Vector クラスと ArrayList クラスの違いを理解しようとしています。ベクトルはおそらく内部的に同期されています。各要素ごとに同期されていますか、それとも全体として同期されていますか? (複数のスレッドが同時にベクトルにアクセスできるケースは想像できましたが、複数のスレッドが同じ要素に同時にアクセスすることはできませんでした)。以下のコードを見ると、私の知る限りでは、キーワードがメソッド シグネチャで使用されると、それを含むクラス オブジェクト (のインスタンス) で同期されるため、getAo()は と同等ではありません。ただし、と同等ですか?同等とは、つまりgetV()synchronizedVectorVsArrayListgetAoSync()getV()aoインスタンス変数は、getter メソッドを介してすべてのアクセスが行われる限り、同期に関して Vector オブジェクトのように動作し始めますか?

public class VectorVsArrayList {

        private ArrayList<?> ao = null;
        private Vector<?> v = null;



        public ArrayList<?> getAoSync(){
            synchronized(ao){
                return ao;
            }
        }


        public synchronized ArrayList<?> getAo() {
            return ao;
        }


        public Vector<?> getV() {
            return v;
        }

    }
4

3 に答える 3

1

簡単な答え: いいえ、同等ではありません。

synchronizedそのあたりで使用するとreturn ao;ArrayListは return 命令中にのみ同期されます。これは、2 つのスレッドがまったく同時にオブジェクトを取得できないことを意味しますが、オブジェクトを取得すると、同時に変更できます。

2 つのスレッドがこのコードを実行する場合、add()はスレッド セーフではありません。

ArrayList<?> list = getAo(); // cannot be executed concurrently
list.add(something); // CAN be executed concurrently

補足:ベクトルを使用しないでください。理由については、この投稿をご覧ください。

于 2014-03-20T17:02:40.220 に答える
1

Vector と同等のことを行うには、コレクション内の任意の要素へのアクセスを保護する必要があります。メソッド getAo は、配列リストへのアクセスを単純に同期します。

2 つのスレッドが getAo を呼び出し、各スレッドがこの配列リストに対して「add」メソッドを呼び出した後で、マルチスレッドの問題が発生する可能性があります (「add」が同期していないため)。

CopyOnWriteArrayList のようなアトミック クラスを確認することをお勧めします: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

于 2014-03-20T17:11:57.707 に答える
1

それらは同等ではありません。あなたが探しているのはCollections.synchronizedList、を含む任意のリストを「ラップアラウンド」できるものですArrayList

于 2014-03-20T17:05:02.533 に答える