1

multiThread Java アプリケーションがあります。1 つの方法では、ArrayList を同期する必要があります。arrayList はスレッド セーフではないため、同期を使用する必要があります。問題は、ArrayList の型であるオブジェクトがオブジェクトのメンバー変数ではないことです。メソッドのプロトタイプは次のとおりです。

public void simultaneousAccess(ArrayListWrapper aListWrapper){
  ArrayList list = aListWrapper.getList();
  //...Codes manipulate the list            
}

マルチスレッドのため、使用しますか

A)

 public void synchronized simultaneousAccess(ArrayListWrapper aListWrapper){
         ArrayList list = aListWrapper.getList();
         //...Codes manipulate the list            
    }

または

B)

public void simultaneousAccess(ArrayListWrapper aListWrapper){
     ArrayList list = aListWrapper.getList();
     Synchronized(list){
         //...Codes manipulate the list 
     }           
 }

パフォーマンス テストから、どちらも機能しません。しかし、私はなぜわからないのですか?

ソースコード全体は次のとおりです。

package com.juhani.prototype.sync;

import java.util.ArrayList;

public class ArrayListWrapper {
    public ArrayList<Integer> aList = new ArrayList<Integer>();

    public ArrayListWrapper(){
        Integer one = new Integer(1);
        Integer two = new Integer(2);
        Integer three = new Integer(3);

        aList.add(one);
        aList.add(two);
        aList.add(three);
    }
}

package com.juhani.prototype.sync;

import java.util.ArrayList;

public class TestClass {

    public int count_test=0;

    public synchronized void test(ArrayListWrapper listWrapper){        
        ArrayList<Integer> list = listWrapper.aList;  
        int temp = list.get(1)+1;
        list.set(1,temp);       
    }

    public void testBlock(ArrayListWrapper listWrapper){
        ArrayList<Integer> list = listWrapper.aList;  
        synchronized(list){
            int temp = list.get(1)+1;
            list.set(1,temp);     
        }
    }

}


package com.juhani.prototype.sync;

public class WorkerSyncObj extends Thread {

    ArrayListWrapper listWrapper = null;
    TestClass tc = null;
    int number;

    public WorkerSyncObj(int aNumber){
       number = aNumber;    
    }

    public void setListWrapper(ArrayListWrapper aListWrapper){
        listWrapper = aListWrapper;
    }

    public void setTestClass(TestClass aTc){
        tc = aTc;
    }

    public void run(){
        int i = 1000;
        for(int j=0;j<i;j++){
            tc.testBlock(listWrapper);
            System.out.println("Thread "+number+" is runing at loop "+j+" . index 1 value is:"+listWrapper.aList.get(1)); 
        }       
    }   
}

package com.juhani.prototype.sync.main;

import com.juhani.prototype.sync.ArrayListWrapper;
import com.juhani.prototype.sync.TestClass;
import com.juhani.prototype.sync.WorkerSyncObj;

public class TestMain {

    public static void main(String[] args){

        ArrayListWrapper list = new ArrayListWrapper();
        TestClass tc = new TestClass();

        WorkerSyncObj work1 = new WorkerSyncObj(1);
        work1.setListWrapper(list);
        work1.setTestClass(tc);
        WorkerSyncObj work2 = new WorkerSyncObj(2);
        work2.setListWrapper(list);
        work2.setTestClass(tc);
        WorkerSyncObj work3 = new WorkerSyncObj(3);
        work3.setListWrapper(list);
        work3.setTestClass(tc);

        work1.start();
        work2.start();
        work3.start();



    }

}
4

2 に答える 2

5

最初のケースではthisオブジェクトをロックし、2 番目のケースではオブジェクトをロックしlistます。異なるオブジェクトからメソッドを呼び出しても、リストは同じである場合、これは問題になる可能性があります。これが、最初のケースの例外の理由である可能性があります。または、またはなど
の組み込みの同時実行型を試すこともできます。Collections.synchronizedListCopyOnWriteArrayList

于 2012-07-09T06:53:38.623 に答える
0

Javaでは、すべてのオブジェクトインスタンスに固有のロック(および対応するクラス自体)があります。同期されたキーワークは、実際には排他的アクセスに固有のロックを使用します。

syncrhonized method(...) {...} 

に等しい

method(...) { 
this.intrinsicLock.lock(); 
...; 
this.intrinsicLock.unlock() }

synchronized( obj_ref ) { ... }

に等しい

obj_ref.intrinsicLock.lock(); 
{...} 
obj_ref.instrinsicLock.unlock();

したがって、同期されたメソッドは、リスト(パラメーター)の保護には適していません。同期(リスト)を使用する場合、2つの問題があります。1。排他的アクセスの粒度が少し粗雑に見える2.プログラム全体のどこでもすべてのリストアクセスで「同期(リスト)」も使用する必要があります。これはプロトコルです(排他的アクセス用)。

これが、Javaライブラリがかなりの数の同時データ構造を提供する理由です。

于 2012-07-12T05:54:44.353 に答える