在下面的代码中;由于系统级锁定(addConfLock),在将新的会议(addConference()API)添加到集合中时,许多线程在我的系统中被阻止。每个新会议线程的添加都被阻止;并且增加了添加 conf 的时间,因为每个会议对象都必须通过执行复杂的 sql 从数据库创建/构建。因此,线程阻塞时间与数据库事务成正比。
我想将 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
}
}
正如您所说,问题是您为每个 conf id 锁定了所有内容。如何更改锁定机制的设计,以便每个 conf id 都有单独的锁,然后只有当事务针对相同的 conf id 时,您才会锁定,否则执行将是并行的。
以下是 yo 如何实现它:
- 您的
Conferences
应该使用COncurrentHashMap来存储不同的conf。 - 锁定您从
conf = confs.get(confID)
检索的conf对象,即同步(conf)。
然后,您的应用程序应该性能会更好。
编辑:
问题出在此代码中:
synchronized(addConfLock) {
conf = confs.get(confID)
if(conf != null)
{ return true;}
conf = Conf.getInstance(confID, conn);
}
如果您使用ConcurrentHashMap
作为集合,则可以将其删除,它提供了一个 api putIfAbsent
,因此您无需锁定它。