0

在下面的代码中;由于系统级锁定 (addConfLock),在将新会议 (addConference() API) 添加到集合中时,我的系统中的许多线程都被阻塞了。每个新会议线程的添加都被阻止;由于必须通过执行复杂的 sql 从数据库创建/构建每个会议对象,因此添加 conf 的时间增加了。所以线程阻塞时间与数据库事务成正比。

我想将 conf 对象创建与将 conf 添加到集合中的 SYNC 块分开。
我尝试了一个解决方案;如果有任何其他解决方案,请指导我或向我解释我的解决方案的坏处。

下面是原始代码。

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应该使用 COncurrentHashMap 来存储不同的 conf。
  2. 锁定您从中检索的 conf 对象,conf = confs.get(confID)即 synchronize(conf)。

你的应用程序应该会执行得更好。

编辑:

问题出在这段代码中:

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

如果你ConcurrentHashMap用作集合,你可以删除它,它提供了一个 api putIfAbsent,所以你不需要锁定它。

于 2013-10-02T07:03:16.457 回答