I have a static Map, which I need to synchronize access to. The map is keyed by a user id. I want to optimize the synchronization such that I don’t block all threads where I could block only threads that relate to the same user id.
private static Object s_lock = new Object();
private static Map<String,User> s_users = new HashMap();
...
private someMethod() {
synchronized(s_lock)
{
// keeping the global lock for as little as possible
user=getMapEntry();
}
synchronized(user) <-------- (1)
{
// time consuming operation
// hopefully only blocking threads that relate to same user id.
}
}
...
private User getMapEntry(String userId)
{
if (s_users.containsKey(userId)) {
user = s_users.get(userId);
}
else {
user = new User();
user.id = userId;
s_users.put(userId, user);
}
return user;
}
My question is – at (1) I am assuming that I am not holding the ‘global’ sync lock, but as the s_users map is static, are the entries effectively static, meaning that I am still holding the global lock (i.e. sync’ing on the class object)?
Nope, you’re good: each map-entry is a separate object, so synchronizing on a map-entry won’t synchronize on the map, nor on the class that owns the map.
(By the way, your #getMapEntry(…) method actually returns a value, rather than an entry. A map entry contains references both to a key and to a value.)