Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java combine explicit locks with synchronized methods

I have a thread safe class Container:

public class Container {
  private int x;
  ...
  public synchronized int getX();
  public synchronized void setX(int x);
}

Then I have a list of containers:

List<Container> containers;

I would like to iterate through the list, aquire the container's lock at each iteration and, only at the end of loop, release all locks. Something like this:

for(Container c : containers) {
  c.lock();
  //do stuff
}
for(Container c : containers)
  c.unlock();

I still want other threads to be able to continue to use getX and setX methods of unlocked containers, but for various reasons I do not want to allow that for already analysed containers.

Do you know the java code for that?

Better ideas are also appreciated.

like image 208
Kami Avatar asked Nov 10 '22 11:11

Kami


1 Answers

This is not possible I'm afraid. The Java Language imposes a strict nesting principle with the synchronized (...) { ... } blocks (and synchronized methods).

That being said, there are nasty workarounds. In bytecode a synchronized block translates to two separate monitorenter / monitorexit instructions. The same thing can be achieved with sun.mis.Unsafe.monitorEnter() and monitorExit().

In this case however, I would strongly encourage you to rethink the design. I would suggest you let getX and setX acquire / release an internal Lock (which the traversal method also uses). In particular, you could use ReadWriteLock for your setX and getX methods. In fact, this approach is better than having synchronized methods for other reasons too. See for instance:

Why is it a good practice to have separate locks instead of having lock on object that get modified in the synchronized block in java?

like image 128
aioobe Avatar answered Nov 14 '22 22:11

aioobe