How do synchronized static methods work in Java and can I use it for loading Hibernate entities?
Solution 1:
To address the question more generally...
Keep in mind that using synchronized on methods is really just shorthand (assume class is SomeClass):
synchronized static void foo() {
...
}
is the same as
static void foo() {
synchronized(SomeClass.class) {
...
}
}
and
synchronized void foo() {
...
}
is the same as
void foo() {
synchronized(this) {
...
}
}
You can use any object as the lock. If you want to lock subsets of static methods, you can
class SomeClass {
private static final Object LOCK_1 = new Object() {};
private static final Object LOCK_2 = new Object() {};
static void foo() {
synchronized(LOCK_1) {...}
}
static void fee() {
synchronized(LOCK_1) {...}
}
static void fie() {
synchronized(LOCK_2) {...}
}
static void fo() {
synchronized(LOCK_2) {...}
}
}
(for non-static methods, you would want to make the locks be non-static fields)
Solution 2:
By using synchronized on a static method lock you will synchronize the class methods and attributes ( as opposed to instance methods and attributes )
So your assumption is correct.
I am wondering if making the method synchronized is the right approach to ensure thread-safety.
Not really. You should let your RDBMS do that work instead. They are good at this kind of stuff.
The only thing you will get by synchronizing the access to the database is to make your application terribly slow. Further more, in the code you posted you're building a Session Factory each time, that way, your application will spend more time accessing the DB than performing the actual job.
Imagine the following scenario:
Client A and B attempt to insert different information into record X of table T.
With your approach the only thing you're getting is to make sure one is called after the other, when this would happen anyway in the DB, because the RDBMS will prevent them from inserting half information from A and half from B at the same time. The result will be the same but only 5 times ( or more ) slower.
Probably it could be better to take a look at the "Transactions and Concurrency" chapter in the Hibernate documentation. Most of the times the problems you're trying to solve, have been solved already and a much better way.
Solution 3:
Static methods use the class as the object for locking, which is Utils.class for your example. So yes, it is OK.
Solution 4:
static synchronized
means holding lock on the the class's Class
object
where as
synchronized
means holding lock on that class's object itself. That means, if you are accessing a non-static synchronized method in a thread (of execution) you still can access a static synchronized method using another thread.
So, accessing two same kind of methods(either two static or two non-static methods) at any point of time by more than a thread is not possible.