What is the difference between synchronized(this) and synchronized(ClassName.class)? - java

I read somewhere that synchronized(this) should be avoided for various reasons. Yet some respectable code that I encountered uses the following in the constructor:
public SomeClass(Context context) {
if (double_checked_lock == null) {
synchronized (SomeClass.class) {
if (double_checked_lock == null) {
// some code here
}
}
}
}
Is there really a difference between synchronized(this) and synchronized(SomeClass.class)?

synchronized(this) is synchronized on the current object, so only one thread can access each instance, but different threads can access different instances. E.g. you can have one instance per thread.
This is typically useful to prevent multiple threads from updating an object at the same time, which could create inconsistent state.
synchronized(SomeClass.class) is synchronized on the class of the current object ( or another class if one wished) so only one thread at a time can access any instances of that class.
This might be used to protect data that is shared across all instances of a class (an instance cache, or a counter of the total number of instances, perhaps) from getting into an inconsistent state .

this is different for each instance.
ClassName.class is not.
Therefore, synchronized(this) will allow multiple instance to run simultaneously.

The synchronized keyword, when applied to a class locks on the class, and when it's applied to this locks on the current object instance. From the Java Language Specification, section 8.4.3.6, 'synchronized Methods':
A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.

Each java Object can have a lock. This lock can be held by at most one thread at a time, any other thread has to wait to get the lock of the same object.
synchronized(this) acquires the lock of the instance this for the current thread. The method can run parallel on different instances (different values for this and therefore different locks)
synchronized(SomeClass.class) acquires the lock of the global class object of SomeClass. Only one instance of the method can run as all object instances lock on the same global object (same lock).

These are 2 different object to lock on:
'this' refer to current instance context, so creating multiple instances will have no effect if, for example, each thread using a different instance and lock on it. 'this' can be referred only on non-static context.
the 'class' is a static member of the Java Class and there is exactly one instance of it. You can lock on it in both static and non-static context.

synchronized(this) synchronizes on the instance of the object.
synchronized(SomeClass.class)uses the instance of the Class object that represents SomeClass, which is global for all instances in the same classloader.
Thus, these are different constructs with different semantics.
Using synchronized alone, or as a method modifier, also synchronizes on the instance's semaphore, which is normally used to prevent contention between multiple threads accessing that instance as a shared resource (i.e. a List).
The thread you refer states that it's a better practice to use a private instance, as synchronizing directly on your object instance may be dangerous. For that you'd use:
class MySharedResourceClass {
private SomeClass lock = new SomeClass();
public doSomething() {
synchronized (lock) {
// Do something here
}
}
}

Related

Java method vs member synchronization

I know that java's synchronization primitive, when applied to a method, is the semantic equivalent of taking a lock out on the object itself for the duration of the method's execution.
However, I'm unclear on this primitive's contract w.r.t. methods that access specific members of the object concurrently. Is the contract that this primitive only protects concurrent access across other members that also use it, or across any member that synchronizes on any underlying member of this object?
For instance, If foo() and bar() in the example below are invoked concurrently, can this lead to data races on innerThing?
class Thing {
InnerThing innerThing;
OtherInnerThing otherInnerThing;
public synchronized void foo() {
innerThing.mutate();
}
public void bar() {
synchronized(innerThing) {
innerThing.mutate();
}
}
}
Is the contract that this primitive only protects
concurrent access across other members that also
use it, or across any member that synchronizes on
any underlying member of this object.
The former. All threads must synchronize on the same object.
If thread 1 is sync'd on the instance, and thread 2 attempts to sync on some member object of that instance, thread 2 will not be blocked.
This is implicit in the Java Language Specification; the wording talks about 'the same monitor'.

java: running thread methods in the same class

I have three threads on the same class i.e
Thread A obj, Thread B obj, Thread C obj and that class contains 3 static synchronized methods so when we start the 3 threadssaya.meth1, b.meth2, c.meth3what will happen – does all three will execute or only one ?`
Update:
interviewr asked me this question so actually i do have any code to write it here
The methods are static and synchronized.. So, the lock will be on the class object.. Not on the instances of the class.. So the methods will run one after another.... Thread2 and Thread3 will have to wait until thread1 completes method1().. syncronization is NOT at method level.. it is always at object level... beit instance object or class object.
then they will execute it one by one in serial manner as the methods are static synchronized. So the lock will be held at Class Level not the method level. Hence one thread will acquire lock and others will have to wait.
You should try running this and see.
Once you invoke a synchronized method, the VM will automatically ask a grant of access for the object on which you are invoking the method. If that is given it will enter the synchronized method. Upon exit til will release this access right. While holding the rights, no-one else is allowed into any synchronized method on the same object, effectively serializing the requests.
does that make sense?
Synchronization is designed to make things thread-safe and avoid race conditions, and this fashion reduce access to at most one thread. There is no way for the program to find out whether two synchronized methods A and B are otherwise connected, so it has the policy of least tolerance.
If you have more synchronization that necessary, e.g. that A and B needs to be mutually exclusive and C and D needs to be mutually exclusive, but not between, say A and C then the advice is typically to modularise your code so A+B goes into one object while C+D goes into another, hence avoiding to step over each others toes
If execution for objects of the same class attempt to enter the same synchronized method (whether static or not)from different threads, they will be synchronized (i.e. execute one at a time).
The primary difference between static synchronized methods and non static synchronized methodsis that non-static synchronized methods hold a lock on the instance of the class whereas static synchronized methods lock on the class object.
Since in java there exists one class object per class, only one thread can execute inside a static synchronized method in the same class.
For non-static synchronized methods only one thread can execute inside a static synchronized method in the same object
And one more point is that synchronization is at object level not as method level.

What is the use of static synchronized method in java?

I have one question in my mind. I have read that static synchronized method locks in the class object
and synchronized method locks the current instance of an object. So what's the meaning of locked
on class object?
Can anyone please help me on this topic?
In general, synchronized methods are used to protect access to resources that are accessed concurrently. When a resource that is being accessed concurrently belongs to each instance of your class, you use a synchronized instance method; when the resource belongs to all instances (i.e. when it is in a static variable) then you use a synchronized static method to access it.
For example, you could make a static factory method that keeps a "registry" of all objects that it has produced. A natural place for such registry would be a static collection. If your factory is used from multiple threads, you need to make the factory method synchronized (or have a synchronized block inside the method) to protect access to the shared static collection.
Note that using synchronized without a specific lock object is generally not the safest choice when you are building a library to be used in code written by others. This is because malicious code could synchronize on your object or a class to block your own methods from executing. To protect your code against this, create a private "lock" object, instance or static, and synchronize on that object instead.
At run time every loaded class has an instance of a Class object. That is the object that is used as the shared lock object by static synchronized methods. (Any synchronized method or block has to lock on some shared object.)
You can also synchronize on this object manually if wanted (whether in a static method or not). These three methods behave the same, allowing only one thread at a time into the inner block:
class Foo {
static synchronized void methodA() {
// ...
}
static void methodB() {
synchronized (Foo.class) {
// ...
}
}
static void methodC() {
Object lock = Foo.class;
synchronized (lock) {
// ...
}
}
}
The intended purpose of static synchronized methods is when you want to allow only one thread at a time to use some mutable state stored in static variables of a class.
Nowadays, Java has more powerful concurrency features, in java.util.concurrent and its subpackages, but the core Java 1.0 constructs such as synchronized methods are still valid and usable.
In simple words a static synchronized method will lock the class instead of the object, and it will lock the class because the keyword static means: "class instead of instance".
The keyword synchronized means that only one thread can access the method at a time.
And static synchronized mean:
Only one thread can access the class at one time.
Suppose there are multiple static synchronized methods (m1, m2, m3, m4) in a class, and suppose one thread is accessing m1, then no other thread at the same time can access any other static synchronized methods.
static methods can be synchronized. But you have one lock per class. when the java class is loaded coresponding java.lang.class class object is there. That object's lock is needed for.static synchronized methods.
So when you have a static field which should be restricted to be accessed by multiple threads at once you can set those fields private and create public static synchronized setters or getters to access those fields.
Java VM contains a single class object per class. Each class may have some shared variables called static variables. If the critical section of the code plays with these variables in a concurrent environment, then we need to make that particular section as synchronized. When there is more than one static synchronized method only one of them will be executed at a time without preemption. That's what lock on class object does.

Lock implemention on "Class" class object for synchronization

I was going through this link . According to this :
Class locks are actually implemented as object locks. When the JVM loads a class file, it creates an instance of class java.lang.Class. When you lock a class, you are actually locking that class's Class object.
But according to java spec , all objects of same type(class) on heap share single Class object.
So how can this be true for multi-thread synchronized access to Objects?
A class lock
synchronized (String.class) {...}
An object lock
//doesn't matter what the lock object is as long as it's not null
private final Object lock = new Object();
...
synchronized (lock) {...} // will throw NPE if lock is null
They're both considered object locks because String.class returns an instance of Class<String>.
In the class lock, the thread acquires the Class<String> instance monitor. In the object lock, the thread acquires the String instance monitor.
But according to java spec , all objects of same type(class) on heap share single Class object. So how can this be true for multi-thread synchronized access to Objects?
Only synchronized static methods would require a thread to acquire the class object's lock. All the synchronized instance methods would need the related instance object's lock which isn't shared.
But according to java spec , all objects of same type(class) on heap
share single Class object. So how can this be true for multi-thread
synchronized access to Objects?
Class level locks make more sense in static methods. If you use the synchronized keyword on a static method, the object whose monitor is used for the lock is the class object, i.e. the one represented by the literal Class.class.

Can one thread access a synchronized non-static method and another thread access a synchronized static method at the same time?

I got this asked in an interview a few days ago. Can one thread access a synchronized non-static method and another thread access a synchronized static method at the same time? The methods belong to the same class. I know the answer is yes but I want to know how it is possible. Thanks.
The synchronization object for a non-static method is the object itself (this).
The synchronization object for a static method is the .class instance.
Both are different. Hence you can.
The important thing to consider, is what object are those methods being synchronized on? For a non-static (just a regular, object method) it will be synchronized on the actual instance of the class (this - the object you create using 'new'). For a static method, you are synchronizing it on the class itself (there is no instance object).
These are two different objects, so the synchronization will not stop the methods running at the same time.
Because syncrhonization is not enforced on the same two objects:
first synchronized lock (for non-static method) is acquired over the object instance,
second synchronized lock (for static method) is acquired over the class instance.
If you have a synchronized non-static method on a class, the lock object will be YourClass.this. If you have a static synchronized method on the same class, the lock object will be the YourClass.class. These are two different locks that does not mutually exclude each other. So that is the reason why the two threads can access the two methods in the same time.
ObPedantry: Not if this is java.lang.Class.class (and the lock hasn't been released by calling a java.lang.Object.wait).

Categories

Resources