Yes, you can synchronize using an array as monitor object, because arrays (even arrays of primitives) are objects in Java.
You can synchronize a block of code on a specific monitor like this:
public void myMethod() {
unsynchronized_statements...
synchronized(myMonitorObject) {
synchronized_statments...
}
It is best practice to synchronize as few lines of code as possible.
Synchronizing code on a monitor does not affect the monitor in any way, it only affects the threads accessing the synchronized block of code. Before thread execution can enter the block of code, it must obtain 'the lock' on the monitor. The Java runtime ensures that at most one thread at a time can have 'the lock' on a monitor. So synchronizing on your array does not prohibit unsynchronized blocks of code to access it! The trick is to make sure that all the operations you don't want to happen at the same time are within blocks synchronized on the same monitor.
Since Java does not offer multi-dimensional arrays, only arrays-of-arrays, you can certainly synchronize on a nested array for more fine-grained synchronization. If you model a 2d array as an array of rows, you can only synchronize on rows, not on columns because in that example columns are not represented as separate arrays.
You can only synchronize on single array values if these are non-primitve, so Integer() instead of int. Note that Integer() is an immutable object, so you would not be able to change its value. A solution would be to create your own Cell() wrapper object with a getter and setter for the contained numeric value. This would allow you to let a thread get a lock on the Cell and safely change its value.
Because it's my day off I decided to have some fun and created a working example of what you describe. Yes, this is my idea of having fun.
Classes:
- Matrix : representation of a 2d matrix of cells
- Cell : wrapper for a matrix cell value
- Operation : An abstract operation on an array of Cells
- IncrementOperation : an Operation which increments each Cell value
- ReverseOperation : an Operation which reverses the order of the cells
- Main : the application
The application starts multiple operations on the same matrix. The only synchronized block of code is in the class Operation. If you remove the synchronization, the results will be wrong because two operations are manipulating the same row simultaneously.
Output when synchronized:
[105, 104, 103, 102, 101]
[110, 109, 108, 107, 106]
[115, 114, 113, 112, 111]
[120, 119, 118, 117, 116]
[125, 124, 123, 122, 121]
[130, 129, 128, 127, 126]
[135, 134, 133, 132, 131]
[140, 139, 138, 137, 136]
[145, 144, 143, 142, 141]
[150, 149, 148, 147, 146]
Example output when NOT synchronized:
[105, 4, 103, 102, 101]
[110, 9, 108, 207, 106]
[115, 14, 113, 212, 111]
[120, 19, 118, 217, 116]
[125, 124, 123, 122, 121]
[130, 129, 128, 127, 126]
[135, 34, 133, 232, 131]
[140, 139, 138, 137, 136]
[145, 144, 143, 142, 141]
[150, 149, 148, 147, 146]
Note that I added some Thread.sleep() statements in the operation implementations to make the difference between synchronized and unsynchronized execution more obvious.