fork download
  1. import java.util.HashMap;
  2. import java.util.concurrent.atomic.AtomicInteger;
  3.  
  4.  
  5. public class Main {
  6.  
  7. // it is no advantage of using ConcurrencyHashMap, because of
  8. // put with increment or remove with decrement must be atomic operations
  9. // AtomicInteger is just a int value holder
  10. private static final HashMap<Object, AtomicInteger> locks = new HashMap<Object, AtomicInteger>();
  11.  
  12. public static void saveSomethingImportantToDataBase(Object id) {
  13. // put lock
  14. AtomicInteger lock;
  15. synchronized (locks) {
  16. lock = locks.get(id);
  17. if (lock==null) {
  18. lock = new AtomicInteger (1);
  19. locks.put(id, lock);
  20. }
  21. else lock.incrementAndGet();
  22. }
  23. // synchronized work
  24. synchronized (lock) {
  25. System.out.println("begin");
  26. try { Thread.sleep(1000); } catch (InterruptedException e) {}
  27. System.out.println("end");
  28. }
  29. try { Thread.sleep(500); } catch (InterruptedException e) {}
  30. // remove lock
  31. synchronized (locks) {
  32. lock.decrementAndGet();
  33. if (lock.get()==0) locks.remove(id);
  34. }
  35. }
  36.  
  37. public static Thread startTestThread() {
  38. Thread thread = new Thread() { public void run() { saveSomethingImportantToDataBase(1); } };
  39. thread.start();
  40. return thread;
  41. }
  42.  
  43. public static void main(String[] args) throws Exception {
  44. startTestThread();
  45. startTestThread();
  46. Thread.sleep(1000+500+100);
  47. startTestThread();
  48. }
  49.  
  50. }
Success #stdin #stdout 0.08s 380864KB
stdin
Standard input is empty
stdout
begin
end
begin
end
begin
end