I am following a tutorial and it basically explains about the cause of race condition which happens when resizing Hashmap in a multithreaded environment:
Actually there is at least one race condition related to rehashing. Look at this code fragment (it is from Sun JDK7):
boolean oldAltHashing = this.useAltHashing;
this.useAltHashing |= sun.misc.VM.isBooted() && (this.newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean rehash = oldAltHashing ^ this.useAltHashing;
transfer(newTable, rehash);
this.table = newTable;
Here It is possible that thread T1 ends up with rehash = true
and thread T2 ends up with rehash = false
(let's suppose T1 has already changed the value of this.useAltHashing
).
Now, guess that which thread will write the this.table
- you have no idea, either can. So, it's a question of luck whether you get a consistent internal state or not.
Anyway, as I mentioned in my comment by design, it is not supposed to use HashMap in a multithreaded environment. It will not work. Either because of this, or because of other reasons. The above was just one example why you shouldn't try to go against the contracts.
I don't know if the example is valid. What is clear is that it is implementation-specific. I think it also misses the bigger picture.
HashMap
's contract clear states (emphasis theirs):
If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)
If you break the contract, all bets are off. The map is free to blow up in arbitrary, unspecified, ways.
The answer for your first question is in the quoted text:
"because java HashMap doesn't append the new element at tail instead it append new element at head to avoid tail traversing"
If HashMap would store them in insertion order it had to traverse the list at each insertion or store an extra pointer to the end of the list (and maintain it). Anyhow storing the elements in the bucket in insertion order would not give any benefits (at least I can't think of any).
The answer to your second question relies here:
http://mailinator.blogspot.hu/2009/06/beautiful-race-condition.html