jQuery in Action, 2nd edition*
The moose likes Threads and Synchronization and the fly likes HashMap Concurrency question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "HashMap Concurrency question" Watch "HashMap Concurrency question" New topic
Author

HashMap Concurrency question

Promod kumar
Ranch Hand

Joined: Jun 26, 2006
Posts: 90
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
Marshal

Joined: Mar 22, 2005
Posts: 42281
    
  64
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.


Ping & DNS - my free Android networking tools app
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40

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


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Alan Mehio
Ranch Hand

Joined: Apr 04, 2005
Posts: 73


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






Regards,
Alan Mehio
London, UK
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42281
    
  64
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

Joined: Jun 26, 2006
Posts: 90
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.
 
 
subject: HashMap Concurrency question