title: How can we have entry-level locking in HashMap?
body: <p>Since, statckoverflow does not allow add more thing to your question in the original question (you can only add comment, not code) I am asking a sequential question to my original question here: 
  <a href="https://stackoverflow.com/questions/38470322/can-we-use-synchronized-for-each-entry-instead-of-concurrenthashmap/38470603?noredirect=1#comment64386235_38470603">Can we use Synchronized for each entry instead of ConcurrentHashMap?</a></p>
  
  <p>The problem is very simple, and I don't know why for such a simple problem that probably many people have encountered before me I should spend this much time :/ </p>
  
  <p>The problem is: I have a hashmap, I want when one thread is working on one of the entries of the hashMap, no any other thread access that object, and I don't want to lock the whole hashMap. </p>
  
  <p>I know that java provides ConcurrentHashMap, but ConcurrentHashMap does not solve the problem, when you want to do thing more complex than simple put and get. Even newly added functions (in Java 8) like merge is not enough for complex scenarios.</p>
  
  <p>For example: </p>
  
  <p><strong><em>Suppose I want a hash map that maps strings to ArrayLists. Then for example suppose I want to do this: 
  For key k, if there is any entry, add newString to its ArrayList, but if there is no entry for k, create the entry for k such that its ArrayList has newString.</em></strong> </p>
  
  <p>I was thinking I can do it as follows: </p>
  
  <pre><code>                ArrayList&lt;String&gt; tm =new ArrayList&lt;String&gt;();
                  tm.add(newString);
                  Object result = map.putIfAbsent(k, tm);
                  if  (result != null)
                  {
                      map.get(k).add(newString);
                  }
  </code></pre>
  
  <p>But it does not work, why? suppose putIfAbset return something other than null, then it means that map already has an entry with key k, so I will try to add newString to the ArrayList of the already existing entry, but right before adding, another thread may remove the entry, and then I will get NullPointerException! </p>
  
  <p>So, I found it very difficult to code such things properly. </p>
  
  <p>But I was thinking that if I can simply lock that entry, life will be wonderful! </p>
  
  <p>In my previous post I suggested something very simple that in fact eliminates the need for concurrentHashMap, and provide entry-level locking but some said that is not true because Long is not immutable ... that I didn't get it well. </p>
  
  <p>Now, I implemented and tested it, it looks good to me, but I don't know why other more experienced developers here told me it is not thread-safe :(  </p>
  
  <p>This is the exact code that I tested: </p>
  
  <p>MainThread: </p>
  
  <pre><code>import java.util.HashMap;
  
  public class mainThread {
  
  public static HashMap&lt;String, Long&gt; map = new HashMap&lt;String, Long&gt;();
  
  public static void main (String args[])
  {
      map.put("k1", new Long(32));
  
  
      synchronized(map.get("k1"))
      {
          Thread t = new Thread(new threadA());
          t.start();
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
  
      }
  }
  }
  </code></pre>
  
  <p>ThreadA: </p>
  
  <pre><code>public class ThreadA implements Runnable {
  
      @Override
      public void run() {
      mainThread.map.put("k2", new Long(21));
      System.out.println(mainThread.map.get("k2"));
  
  
      synchronized (mainThread.map.get("k1")) {
          System.out.println("Insdie synchronized of threadA");
      }
  }
  }
  </code></pre>
  
  <p>It works fine! It prints 21, and after 5 seconds, that mainThread release the lock of map.get("k1"), it prints "Insdie synchronized of threadA"</p>
  
  <p>So, why using this simple approach we cannot provide entry-level locking?! why concurrency should be that much complicated Lol (just kidding) </p>