Reputation: 6593
I am looking for clarification about synchronized blocks. Consider this class -
public class A{
Map map;
public getValue(String key){
return map.get(key);
}
public remove(String key){
synchronized(map){
map.remove(key);
}
}
}
A is a singleton. getValue is heavily accessed throughout the app by multiple threads. I am adding a new method, remove, that removes a key from the map. If remove is implemented as above,
I want the getValue threads to block only if there is a thread performing the remove operation.
Upvotes: 0
Views: 549
Reputation: 198211
The one rule of synchronized is that only one thread can be in a synchronized(foo)
block at a time, for the same foo. That's the only rule of synchronized
.
Well, there's some complicated stuff about memory barriers and the like, and a single thread can be in several nested synchronized(foo)
blocks for the same foo
at the same time:
void thing() {
synchronized(foo) {
stuff(); // this works fine!
}
}
void stuff() {
synchronized(foo) {
doMoreStuff();
}
}
... but the rule stated above is basically the key to understanding synchronized
.
Upvotes: 0
Reputation: 15518
If I understood correctly your need, you could take a look at the ConcurrentMap and of course ConcurrentHashMap which I believe was introduced with Java 5.0 and supports a level of concurrency.
Upvotes: 4
Reputation: 13374
You have a chicken and egg problem with
I want the getValue threads to block only if there is a thread performing the remove operation.
Without some sort of inter-thread interaction, you cannot figure out whether there is some other thread performing a remove
.
The correct way to implement getValue(...)
is to synchronize on the map.
I recommend dropping your own locking, and using a ConcurrentHashMap
and utilizing a lot of work into concurrent performance.
Upvotes: 0
Reputation: 33544
1. getValue() is not synchronized, when a thread acquires the lock of an object, it has the control over all the synchronized blocks... not the Non-synchronized one.. So other threads can access the getValue() when as thread is in sychronized(map) block
2. Use HashTable, which is a sychronized MAP
Upvotes: 0
Reputation: 53694
You don't show how the Map instance is instantiated, but assuming it is not a thread-safe collection instance, this code is not thread-safe.
Upvotes: 1
Reputation: 1502046
When a thread is in the synchronized block of the remove method, I assume it will acquire a lock on the map object. Does that mean other threads trying to access the map via the getValue method will be blocked?
No. Which means you've got a problem, unless you happen to be using a thread-safe map implementation.
When no thread is in the synchronized block of remove method, will threads accessing the getValue method function as usual i.e. not block each other? (I'd like that too).
They won't block each other, no. Again, you'll need to make sure that's okay with whichever Map
implementation you're using, although it's much more likely to be okay than reading at the same time as writing.
You should consider using a ConcurrentMap
implementation (e.g. ConcurrentHashMap
), at which point you don't need any synchronization at all.
If you can't use that, I'd recommend synchronizing in both getValue
and remove
- and measuring the performance. Acquiring an uncontended lock is reasonably cheap - do you really need to go lock-free? (Using ConcurrentHashMap
is a fairly simple way of avoiding the issue, of course, but you should always consider whether extra complexity is needed to achieve the performance you require before you start micro-optimizing.)
Upvotes: 4