0

この以下のコードでは; 新しい会議 (addConference() API) をコレクションに追加すると、システム レベルのロック (addConfLock) が原因で、多くのスレッドがブロックされます。新しい各会議スレッドの追加はブロックされています。複雑な sql を実行して DB から各会議オブジェクトを作成/構築する必要があるため、conf を追加する時間が長くなります。したがって、スレッド ブロック時間は DB トランザクションに比例します。

コレクションにconfを追加するSYNCブロックからconfオブジェクトの作成を分離したいと思います。
解決策を試しました。他の解決策がある場合は私を案内するか、私の解決策の悪い点を説明してください。

以下が元のコードです。

class Conferences extends OurCollectionImpl 
{
   //Contains all on going conferences
}

//single conference instance 
class Conf {

    String confId;
    Date startTime;
    Date participants;

    public void load()
    {
    // Load conference details from DB, and set its instance memebrs
    }
}

class ConfMgr
{

    Conferences confs = new Conferences();
    Object addConfLock = new Object();

    public boolean addConference(DBConn conn, String confID){

      synchronized(addConfLock) {
         Conf conf = null;

         conf = confs.get(confID)
         if(conf != null)
         { return true;}

         conf = new Conf();
         conf.setConfID(confId);
         conf.load(); //This is the BIG JOB with in SYNC BLOCK NEED TO SEPARATED

         confs.add(conf);
      }
   }

}

//私の解決策

public boolean addConference(DBConn conn, String confID){

   Conf conf = null;
   synchronized(addConfLock) {
     conf = confs.get(confID)
     if(conf != null)
     { return true;}
     conf = Conf.getInstance(confID, conn);
   }

   synchronized(conf.builded) {   //SYNC is liberated to individual conf object level
     if(conf.builded.equals("T")) { 
          return true;
     }
     conf.load(); 

     synchronized(addConfLock) {
        confs.add(conf);
     } 

     conf.builded = "T";
   }

   }
}


//single conference instance 
class Conf {

    String confId;
    Date startTime;
    Date participants;
    String builded = "F"; //This is to avoid building object again.
    private static HashMap<String, Conf> instanceMap = new HashMap<String, Conf>;

    /*
     * Below code will avoid two threads are requesting 
     * to create conference with same confID.
     */
    public static Conf getInstance(DBConn conn, String confID){
        //This below synch will ensure singleTon created per confID
        synchronized(Conf.Class) {   
           Conf conf = instanceMap.get(confID);
           if(conf == null) {
                 conf = new Conf();
                 instanceMap.put(confID, conf);
           }
           return conf;
        }         
    }

    public void load()
    {
    // Load conference details from DB, and set its instance memebrs
    }
}
4

1 に答える 1

0

あなたが述べた問題は、conf idごとにすべてをロックしていることです。ロック メカニズムの設計を変更して、conf id ごとに個別のロックが存在するようにすると、トランザクションが同じ conf id に対するものである場合にのみロックされ、それ以外の場合は実行が並列になります。

これを達成する方法は次のとおりです。

  1. Conferences別のconfを保存するには、CONcurrentHashMapを使用する必要があります。
  2. conf = confs.get(confID)synchronize(conf)から取得した conf オブジェクトをロックします。

その場合、アプリケーションのパフォーマンスが大幅に向上するはずです。

編集:

問題はこのコードにあります:

synchronized(addConfLock) {
     conf = confs.get(confID)
     if(conf != null)
     { return true;}
     conf = Conf.getInstance(confID, conn);
   }

コレクションとして使用する場合ConcurrentHashMap、これを削除できputIfAbsentます。API が提供されるため、ロックする必要はありません。

于 2013-10-02T07:03:16.457 に答える