A synchronized method locks the monitor associated with the instance of the class (ie `this`) or the class (if a `static` method) and prevents others from doing so until the return from the method. A `synchronized` block can lock any monitor (you tell it which) and can have a scope smaller than that of the enclosing method.
On the contrary `synchronized` method in practice should be much slower than a `synchronized` block as `synchronized` method would be making more code sequential.
A synchronized method is a method whose body is encapsulated automatically in a synchronized block.
Thus, this is equal:
public void test()
{
synchronized (this)
{
asd();
}
}
public synchronized void test()
{
asd();
}
ReentrantLock
it is unstructured, unlike synchronized constructs -- i.e. you don't need to use a block structure for locking and can even hold a lock across methods. But it give fairness in locking.
For example :
private ReentrantLock lock;
public void test() {
...
lock.lock();
...
}
public void test() {
...
lock.unlock();
...
}
Such flow is impossible to represent via a single monitor in a synchronized construct.
Static and instance `synchronized` methods are not related to each other, therefore you need to apply some additional synchronization between them, like this:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() {
synchronized (Foo.class) { // Synchronizes with static synchronized methods
return bar;
}
}
}
(though in this case leaving `synchronized` on `get()` doesn't make sense, since it doesn't do anything that requires synchronization on instance).
Beware of deadlocks - since this code aquires multiple locks, it should do it in consistent order, i.e. other synchronized static methods shouldn't try to acquire instance locks.
Also note that this particular task can be solved without synchronization at all, using atomic fields:
class Foo {
private static AtomicInteger bar = new AtomicInteger(0);
public static void inc() { bar.getAndIncrement(); }
public int get() { return bar.get(); }
}