user697911
user697911

Reputation: 10531

how to locally synchronize two maps?

For instance,

class Test{
   static Map a = new ...
   static Map b = new ...

   public void process(){

      ...
      a.put(...);
      b.put(...);
  } 
} 

Do I have to lock like this:

 synchronized(a){
     a.put();
 }

 synchronized(b){
     b.put(b);
 }

This seems to be awkward. Any other right way to do this? Thanks.

Upvotes: 1

Views: 1224

Answers (3)

Vitaly
Vitaly

Reputation: 2790

You can use a dedicated object like

Object mapLock = new Object();

to synchronize on.

Or you can sync on a keeping in mind that even if you need an access to b you need to sync on a.

Synchronizing on this is not a good idea in general. I mean this is a bad habit and doing so may eventually result in bad performance or non-obvious deadlocks if not in this but other applications you make.

Avoid synchronized(this) in Java?

You can also consider using ReadWriteLock from concurrency package.

Upvotes: 1

stevestorey
stevestorey

Reputation: 606

You do need to run both operations within one synchronized block. Worth noting that in your example, you've defined the maps statically while the process() method is an instance method. The synchronizing the method will mean that calls to that instance will be synchronized, but that calls to 2 different instances will not (as the lock used when applying the synchronized keyword to a method is effectively this). You could either make the process() method static, or use a synchronized(Test.class) {} block instead to ensure that there's no racing happening.

You will also need to be careful about how you expose the maps to clients - if you're offering them up as properties, then I would probably wrap them with Collections.unmodifiableMap() to ensure that nothing else can go and screw with them while you're not looking - however that doesn't entirely protect against clients having an "odd" time as they will still see changes happen in potentially unsafe ways. As such, I'd also probably declare the types as ConcurrentHashMap to make things a little safer (although there are still some dangerous operations such as sharing an Iterator between threads)

Upvotes: 0

Franz Kafka
Franz Kafka

Reputation: 10831

No, you need both operations in one synchronized block, otherwise another thread may see inconsistencies between the two maps.

One possible option would be using a synchronized method, or you could use some other private object or one of the maps as an monitor. Here is the synchronized method example:

    static Map a = new ...
   static Map b = new ...

   public synchronized void process(){

      ...
      a.put(...);
      b.put(...);
  } 
} 

Upvotes: 2

Related Questions