import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
// it is no advantage of using ConcurrencyHashMap, because of
// put with increment or remove with decrement must be atomic operations
// AtomicInteger is just a int value holder
private static final HashMap
<Object, AtomicInteger
> locks
= new HashMap
<Object, AtomicInteger
>();
public static void saveSomethingImportantToDataBase
(Object id
) { // put lock
AtomicInteger lock;
synchronized (locks) {
lock = locks.get(id);
if (lock==null) {
lock = new AtomicInteger (1);
locks.put(id, lock);
}
else lock.incrementAndGet();
}
// synchronized work
synchronized (lock) {
}
// remove lock
synchronized (locks) {
lock.decrementAndGet();
if (lock.get()==0) locks.remove(id);
}
}
public static Thread startTestThread
() { Thread thread
= new Thread() { public void run
() { saveSomethingImportantToDataBase
(1); } }; thread.start();
return thread;
}
startTestThread();
startTestThread();
startTestThread();
}
}
aW1wb3J0IGphdmEudXRpbC5IYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLmNvbmN1cnJlbnQuYXRvbWljLkF0b21pY0ludGVnZXI7CiAKCnB1YmxpYyBjbGFzcyBNYWluIHsKICAgIAogICAgLy8gaXQgaXMgbm8gYWR2YW50YWdlIG9mIHVzaW5nIENvbmN1cnJlbmN5SGFzaE1hcCwgYmVjYXVzZSBvZiAKICAgIC8vICBwdXQgd2l0aCBpbmNyZW1lbnQgb3IgcmVtb3ZlIHdpdGggZGVjcmVtZW50IG11c3QgYmUgYXRvbWljIG9wZXJhdGlvbnMKICAgIC8vIEF0b21pY0ludGVnZXIgaXMganVzdCBhIGludCB2YWx1ZSBob2xkZXIKICAgIHByaXZhdGUgc3RhdGljIGZpbmFsIEhhc2hNYXA8T2JqZWN0LCBBdG9taWNJbnRlZ2VyPiBsb2NrcyA9IG5ldyBIYXNoTWFwPE9iamVjdCwgQXRvbWljSW50ZWdlcj4oKTsKIAogICAgcHVibGljIHN0YXRpYyB2b2lkIHNhdmVTb21ldGhpbmdJbXBvcnRhbnRUb0RhdGFCYXNlKE9iamVjdCBpZCkgewogICAgICAgIC8vICAgIHB1dCBsb2NrCiAgICAgICAgQXRvbWljSW50ZWdlciBsb2NrOwogICAgICAgIHN5bmNocm9uaXplZCAobG9ja3MpIHsKICAgICAgICAgICAgbG9jayA9IGxvY2tzLmdldChpZCk7CiAgICAgICAgICAgIGlmIChsb2NrPT1udWxsKSB7CiAgICAgICAgICAgIAlsb2NrID0gbmV3IEF0b21pY0ludGVnZXIgKDEpOwogICAgICAgICAgICAJbG9ja3MucHV0KGlkLCBsb2NrKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlICBsb2NrLmluY3JlbWVudEFuZEdldCgpOwogICAgICAgIH0KICAgICAgICAvLyAgICBzeW5jaHJvbml6ZWQgd29yawogICAgICAgIHN5bmNocm9uaXplZCAobG9jaykgewogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImJlZ2luIik7CiAgICAgICAgICAgIHRyeSAgeyAgVGhyZWFkLnNsZWVwKDEwMDApOyAgfSAgY2F0Y2ggKEludGVycnVwdGVkRXhjZXB0aW9uIGUpICB7fQogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImVuZCIpOwogICAgICAgIH0KICAgICAgICB0cnkgIHsgIFRocmVhZC5zbGVlcCg1MDApOyAgfSAgY2F0Y2ggKEludGVycnVwdGVkRXhjZXB0aW9uIGUpICB7fQogICAgICAgIC8vICAgIHJlbW92ZSBsb2NrCiAgICAgICAgc3luY2hyb25pemVkIChsb2NrcykgewogICAgICAgICAgICBsb2NrLmRlY3JlbWVudEFuZEdldCgpOwogICAgICAgICAgICBpZiAobG9jay5nZXQoKT09MCkgIGxvY2tzLnJlbW92ZShpZCk7CiAgICAgICAgfQogICAgfQogCiAgICBwdWJsaWMgc3RhdGljIFRocmVhZCBzdGFydFRlc3RUaHJlYWQoKSB7CiAgICAgICAgVGhyZWFkIHRocmVhZCA9IG5ldyBUaHJlYWQoKSAgeyAgcHVibGljIHZvaWQgcnVuKCkgIHsgIHNhdmVTb21ldGhpbmdJbXBvcnRhbnRUb0RhdGFCYXNlKDEpOyAgfSAgfTsKICAgICAgICB0aHJlYWQuc3RhcnQoKTsKICAgICAgICByZXR1cm4gdGhyZWFkOwogICAgfQogCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgRXhjZXB0aW9uIHsKICAgICAgICBzdGFydFRlc3RUaHJlYWQoKTsKICAgICAgICBzdGFydFRlc3RUaHJlYWQoKTsKICAgICAgICBUaHJlYWQuc2xlZXAoMTAwMCs1MDArMTAwKTsKICAgICAgICBzdGFydFRlc3RUaHJlYWQoKTsKICAgIH0KIAp9