2

2 个线程从 GenericObjectPool 中声明 2 个可重用实例,并开始处理以下数据集 -

Thread 1 [ Rec1, Rec1, Rec2 ]

Thread 2 [ Rec1, Rec3, Rec2 ]

Thread 3 [ Rec3 ]

必须首先查找这些记录,如果找不到,则仅插入一组表中。因此,在 thread1 中,Rec1两次出现被安全地处理,因为它按顺序运行。但是,由于实例之间存在争用,因为 Pool 中的第二个实例上的 Thread2 也有Rec1 。同样 Rec2 , Rec3 也重复了。所以,我将锁设为静态最终 ..

类本身看起来像这样 -

Method1
--------
loop on all records
check condition1 
If Meets
lock obj
Recheck condition1
if meets
INSERT1
release lock
end loop

和 ..

Method 2
---------
loop on all records
check condition2 
If Meets
lock obj
Recheck condition2
if meets
INSERT2
release lock
end loop

关于“obj”锁的建议?将其设为静态最终将解决它,但由于广泛使用类级别锁定而使程序几乎是连续的。

4

2 回答 2

1

执行操作时不要按住锁。仅使用同步调用来仲裁谁可以处理哪些记录,不在同步块内执行操作,并在完成时发出信号。

所以(在java中):

private final static Object LOCK = new Object();
private final static Set<Integer> busyRecords = new HashSet<Integer>();

public static void waitToWorkOn(int recordNum) {
   synchronized(LOCK) {
      while (busyRecords.contains(recordNum)) {
         LOCK.wait(); //go to sleep
      }
      busyRecords.add(recordNum); //ours now
   }
}

public static void doneWith(int recordNum) {
   synchronized(LOCK) {
      busyRecords.remove(recordNum);
      LOCK.notifyAll(); //wake sleepers up
   }
}

任何使用它的代码都必须使用 try-finally 来确保发送释放信号:

waitToWorkOn(recordNum);
try {
   //do something to record
} finally {
   doneWith(recordNum);
}
于 2013-02-27T05:53:08.593 回答
1

尝试使用java.util.concurrent.ConcurrentLinkedQueue而不是您自己的锁定机制。简单、快速、实用的无阻塞

如果我理解你的问题是正确的,那么你需要分别为方法 1 和方法 2 设置两个不同的队列。调用的步骤loop on all records也将被定义为get element from queue or wait

于 2013-02-27T06:12:55.337 回答