I've read the oracle doc about synchronized methods and how they may introduce a lock to the multithreaded program, but there is one thing that is unclear to me. Are the subsequent calls to an already locked methods queued?
Lets say we have a class:
class Astore {
...
public synchronized void a() {
doSomethingTimeConsuming();
}
...
}
and 3 threads that call astore.a()
final Astore astore = new Astore();
Thread t1 = new Thread(new Runnable() {
public void run() {
astore.a();
doSomethingElse();
astore.a();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
astore.a();
}
});
t2.start();
Thread t3 = new Thread(new Runnable() {
public void run() {
astore.a();
}
});
t3.start();
I'm not sure if I've made the example correctly, but the point is, that 3 threads make a call to the same object with synchronized method almost at the same time.
Will the order of operations be stored in a queue so that the threads invoking will be:
- t1 (as it was called first)
- t2 (was called after T1)
- t3
- t1 again (it was busy doing something with A already while other threads requested method)
Can I safely assume that will be the behavior, or there is no guarantee that this will be the order (or even worse, t2 and t3 might get called in random order)
What is the best practice when multiple threads may need to share data (for instance a socket server with one thread for each active connection - I don't want 6 clients to time out while waiting for the first one to finish a huge upload to a shared data structure)
No, it will not queue calls to the method.
If the call is made from a Thread that already has got the lock (a recursive call, for example), then it will just proceed like normal.
Other threads that attempt to get the lock to be able to make a call will hold there and wait until the lock is released.
The order is not guaranteed, use a fair ReentrantLock if that is important.
folkol is correct.
Actually its depends on the machine's design (CPU)
The callers should wait until the resource got allocated by the CPU. The CPU then randomly choose one of the next caller and allocate the resource for it and lock it (Because of synchroize) until the second caller finishes its job.
If you use ReneterantLock instead of synchronized block there is a fairness parameter that you can set so that the thread that is waiting most gets the lock when lock is released by another thread, You can read more here