Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

HashMap Concurrency question

 
Promod kumar
Ranch Hand
Posts: 90
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a question after running the code from this example, http://blog.pramati.com/blog/2008/07/02/concurrency-and-hashmap/. I understand that HashMap is not threadsafe and you cannot predict the behavior when concurrency is involved, however I am trying to understand what exactly is the reason for the failure. I have a breakpoint in if(retrieved==null) block and I checked the hashmap and the element it is trying to find is not there and hence null is returned. What I don't understand is why the element is not there. There is a put statement before the get statement which should have been executed for the object it is trying to find.

The element was inserted into the HashMap, but because of the resizing due to concurrent access, the element gets discarded? Or Is it the case of one thread not seeing the result of another thread's action. I was reading that it is also possible that statements can be reordered at the CPU level which sounds really crazy.

Can someone shed some light



 
Ulf Dittmer
Rancher
Pie
Posts: 42967
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Concurrent access to a shared object can indeed lead to hard-to-predict and hard-to-debug situations that may seem counter-intuitive (provided at least one of the accesses is a write access).

You need to protect that code from competing threads, maybe through synchronization. Declaring the objects in question as "volatile" also helps, but by itself is not sufficient.

Resizing a collection does not lead to elements being discarded, though.
 
Henry Wong
author
Marshal
Pie
Posts: 20902
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The element was inserted into the HashMap, but because of the resizing due to concurrent access, the element gets discarded?


It's not like the element get discarded, it is more like a corruption of the data structures. And with corrupted data structures, anything can happen, including the lost of elements. And a hashmap doesn't magically resize while one thread is using it -- another thread has to do something to cause the resize, like putting more items into the map.

As a side note... Did you know that with threads (and a lot of processors), it is actually possible to corrupt the link list, that is in the bucket of a hashmap, causing a cycle (unintended circular linked list). This means that a get() method call can actually hang !!

Henry
 
Alan Mehio
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


The element was inserted into the HashMap, but because of the resizing due to concurrent access, the element gets discarded? Or Is it the case of one thread not seeing the result of another thread's action. I was reading that it is also possible that statements can be reordered at the CPU level which sounds really crazy.



Having looked at the supplied link example, the key is the current thread so the scenario is below

hashMap.put(Thread.currentThread(), value); // threadA; remember hasMap is being accessed by many threads
Object retrieved = hashMap.get(Thread.currentThread()); // now ThreadB is the current thread here
if (retrieved == null) {
// Can it ever Happen





 
Ulf Dittmer
Rancher
Pie
Posts: 42967
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That blog post contains highly questionable advice: "As a rule of thumb use Thread safe collections wherever concurrency is involved." is not a good strategy, as it's much too conservative. Using thread-unsafe collections works just fine, provided proper use is made of synchronization, locks, volatile etc.
 
Promod kumar
Ranch Hand
Posts: 90
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Ulf and Henry, What I am getting that concurrent modification of the HashMap leaves it an inconsistent/corrupt state. The other symptom I saw was that the HashMap's size variable and the actual elements in the HashMap (I counted them manually) were not the same, I have a really messed up HashMap.

Alan,
I don't think Thread.currentThread is the key here, you can use any other object to recreate the same behavior. The issue here is concurrent modification of HashMap by multiple threads. Also for Thread B to execute Object retrieved = hashMap.get(Thread.currentThread()); it must have executed the previous put statement at some point.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic