Q:

Can one be using two nested synchronized blocks in order to lock two cells of an array for atomic operation?

I have a class Repository which allocates resources represented as values of the cells array field. The method moves the resources from one cell to another. 
I need to make sure that when we move resources from one cell to another, no other move operations can be performed on the cells in question. That is if a cell (origin cell or destination cell) participates in move operation, we must wait until the current operation completes before we perform another move operation on those cells. There should be no limitation on performing move on different pairs of cells in parallel, for example, move(cells[1], cells[2], 5) and move(cells[4], cells[7], 9) can be performed in parallel.
I thought to use two nested synchronized blocks in order to protect both origin and destination cell. I don't think we need to use wait/notifyAll because we're using synchronized anyway.
Am I on the right track?
This is the code (moveOriginal is the original method and moveSynchronized is the protected one:
public class Repository {
    private Integer[] cells;

    public Repository(int size, int initialValue) {
        cells = new Integer[size];
        for(int i = 0; i < size; i++) {
            cells[i] = initialValue;
        }
    }

    public void moveOriginal(int from, int to, int amount) {
        if(cells[from] >= amount) {
            cells[from] = cells[from] - amount;
            cells[to] = cells[to] + amount;
        }
    }

    public void moveSynchronized(int from, int to, int amount) {
        synchronized(cells[from]) {
            synchronized (cells[to]) {
                if(cells[from] >= amount) {
                    cells[from] = cells[from] - amount;
                    cells[to] = cells[to] + amount;
                }
            }
        }
    }
}

A:

There are multiple issues with this approach.

synchronized locks on the value of the cell[x], an Integer, so as soon as you do this
cells[from] = cells[from] - amount;

synchronizing on cells[from] would be locking a different object.
Integer interns objects representing small values. Locking on a shared object like that may lock you out of an entirely wrong cell.
Availability of shared Integer objects goes beyond your thread. Another thread can obtain shared integers on which you synchronize, and lock you out of cells without gaining access to private data structures of your class.

If you want cell-level locking, create an array of objects that would be used specifically for locking the corresponding cells; do not lock on cell values.

A:

No, you can't do that. For this to work you would need to lock on the array itself, preventing parallel operations.
Integer is immutable, meaning cells[to] = cells[to] + amount puts a different object there, instead of modifying the Integer in it. This will cause problems when synchronized(cells[to]) is referring to different objects at different times.
A simplest way to fix this would be to make a Object[] lockArray = new Object[size]; initialized with Objects and synchronize on those. They won't change during your business logic.
In any case you need nested synchronized scopes. What you also need to do is define an order, e.g. always first synchronize on the smaller value. Otherwise you'll get a deadlock when multiple threads try to do something like move(1, 2); move(2, 1); at the same time.
public void moveSynchronized(int from, int to, int amount) {
    if(from == to || from < 0 || to < 0 || from > cells.length || to.cells.length)
        throw new IllegalArgumentException("Bad values ! " + from + ", " + to);

    // Lock1 is always smaller and locked first
    int lock1 = from < to ? from : to;
    int lock2 = from < to ? to : from;

    synchronized(locks[lock1]) {
        synchronized (locks[lock2]) {
            if(cells[from] >= amount) {
                cells[from] = cells[from] - amount;
                cells[to] = cells[to] + amount;
            }
        }
    }
}

