我想创建一个信号量来防止某个方法一次执行超过1x。如何释放信号并让任何线程继续?
如果任何其他线程请求访问,应该等到信号被释放:
private Map<String, Semaphore> map;
public void test() {
String hash; //prevent to run the long running method with the same hash concurrently
if (map.contains(hash)) {
map.get(hash).aquire(); //wait for release of the lock
callLongRunningMethod();
} else {
Semaphore s = new Semaphore(1);
map.put(hash, s);
callLongRunningMethod();
s.release(); //any number of registered threads should continue
map.remove(hash);
}
}
问题:我如何可以锁定只有一个线程的信号,但其释放,使任何数线程可以在发布后立即继续?
一些澄清:
想象的长时间运行的方法是事务性的方法。查看数据库。如果找不到任何条目,则会发送沉重的XML请求并将其保存到db。另外,也许可能会触发进一步的异步处理,因为这应该是数据的“初始获取”。然后从DB返回对象(在该方法内)。如果DB条目已经存在,它将直接返回实体。
现在,如果多个线程同时访问长时间运行的方法,所有方法都会获取沉重的XML(流量,性能),并且它们都会尝试将相同的对象保存到数据库中(因为长时间运行方法是事务性的)。导致例如非唯一例外。加上所有这些触发可选的异步线程。
当只有一个线程被锁定时,只有第一个线程负责持久化该对象。然后,完成后,所有其他线程都会检测到该条目已经存在于数据库中,并只提供该对象。
为什么不把'callLongRunningMethod'放在'synchronized(this){...}'块中?或'同步(哈希)'? (或者,如果它不是私有的,并且/或者从除此方法以外的其他地方调用,则使'调用LongRunningMethod本身'同步') –
“散列”应该来自哪里,它的意图是什么? – zapl
因为该方法可能正在同时运行*如果散列不同。我可能只是没有相同的散列值。 – membersound