Hopefully I do a decent job of explaining... kind of rushed at the moment...
The answer to your first question:
"why cannot we create a lock for each bucket?"
Is that you can create a lock for each bucket - it just isn't necessarily the best course of action.
The answer to your question:
"Can we ALWAYS state that if we have 8-core processor we do not need more than 8 locked regions in ConcurrentHashMap"
is technically "No", though it depends on what you mean by "need". Having a number of regions that matches your system's maximum concurrency or is slightly greater does not necessarily prevent contention, but in practice it works pretty well. There's nothing stopping two threads from attempting to access the same region at the same time, even if there are other regions that aren't locked.
What you can guarantee by having 8 regions or more on an 8-core processor is that all regions can be accessed simultaneously without contention. If you have 8 cores (not Hyper Threaded) you can perform at most 8 operations at the same time. Even then the ideal number of regions might be more (say, 16) than the number of cores because it will make contention less likely at a low cost (only 8 additional locks).
The benefit from having additional regions eventually diminishes as the number of regions increases relative to your maximum concurrency, which leads to them being a waste of space (memory), as mentioned in the JavaDoc. It's a balance between likelihood of contention (given a lock on one region, what is the probability another thread will attempt to access it) and wasted space.
There are a couple of other factors that will affect performance of a ConcurrentHashMap
:
- Execution time of locked code - it's good practice to make locked code sections small so that they complete quickly and release their locks. The more quickly locks are released, the more quickly contention is resolved.
- Distribution of data - Nicely-distributed data tends to perform better under high concurrency. Having all of your data clustered within a single region means that you will always encounter contention.
- Data access pattern - Accessing different regions of data at the same time will perform better, as your threads won't be contending for resource locks. Having nicely-distributed data doesn't matter if you only attempt to access one region at a time.
No matter how many regions there are, all three of those things can positively or negatively affect performance, and can make the number of regions less relevant. Since they play a big part, they make it less likely that having significantly more regions will help you in general. Since you can only execute so many threads at the same time, having threads that quickly complete their work and release their locks is a better focus.
As to your question about the cache: I'm honestly not sure, but I can take a guess. When you're using the map heavily those locks will end up on the cache and take up space, potentially bumping out other things which could be more useful. Cache is much more scarce than main memory, and cache misses waste a lot of time. I think the idea here is a general aversion to putting lots of things on the cache that don't offer a significant benefit. Taken to the extreme: if the cache is filled with locks (somehow) and every data call goes out to memory, you are taking a performance hit.