Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java synchronized block for more than 1 objects?

I have two arrays, and I need to synchronize access to them across threads. I am going to put them in a synchronized block. The problem is, I can pass only one of them to 'synchronized' st one go.

How do I ensure that the access to both the arrays is synchronized? Do I put them in a class and create an object of it? Or I access the other array only in the synchronized block, and this takes care of synchronized access to it?

Thanks,

like image 770
Chaitanya Avatar asked Dec 05 '09 08:12

Chaitanya


2 Answers

Prior to Java 5, I'd have written things like this:

// pre Java 5 code:
Object lock = new Object();
// ...
synchronized(lock) {
    // do something that requires synchronized access
}

But since Java 5, I'd use classes from java.util.concurrent.locks (personally, I don't find this more complicated or error-prone):

// Java 5 Code Using Locks
Lock lock = // ...
lock.lock();
try {
    // do something that requires synchronized access
}
finally {
    lock.unlock();
}

If you need read-write locking, here is example implemented using read-write locks from Java 5:

private ReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock rLock = rwl.readLock();
private Lock wLock = rwl.writeLock();

private List<String> data = new ArrayList<String>();

public String getData(int index) { 
    rLock.lock();
    try {
       return data.get(index);
    } finally {
        rLock.unlock();
    }
}

public void addData(int index, String element) {
    wLock.lock();
    try {
        data.add(index, element);
    } finally {
        wLock.unlock();
    }
}

Of course, adapt it to suit your needs.

like image 101
Pascal Thivent Avatar answered Nov 15 '22 15:11

Pascal Thivent


Whatever you do don't do this:

synchronized (array1) {
  synchronized (array2) {
    // do stuff
  }
}

This is likely to lead to deadlock unless you are very careful. If you do this approach, you must ensure you have an unchanging partial order on the objects - Google "Dining Philosophers" for discussion of the pitfalls.

Basically what you have to do is create one lock object that you will use if you want to access either array and then use that for all array access. It's coarse-grained but safe. You could do it this way:

public static class TwoArrays {
  private int[] array1 = ...
  private int[] array2 = ...
  private final Object LOCK = new Object();

  public void doUpdate() {
    synchronized (LOCK) {
      ...
    }
  }
}

If you need a finer-grained method you want to use the Java 5+ concurrent utilities such as ReadWriteLock but this will be more complicated to implement and error-prone.

like image 26
cletus Avatar answered Nov 15 '22 16:11

cletus