This question already has answers here:
Concurrency in Java: synchronized static methods
(6 answers)
Closed 8 years ago.
the documentation states that synchronized static methods lock on the class, but i have no idea what that means. Can you explain that ?
public static synchronized Object getObjectById (Class objclass, Long id) {
That means that any time you will access this method, it will be locked and no other thread will be able to access it until the lock is destroyed. In another words, the method content will never be executed at the same time by multiple threads.
Beware though as synchronization, by nature, slows down the application as threads may have to wait a bit to continue their execution
Basically it means, that if you have static synchronized methods in class Foo, they cannot run simultaneously. If 2 threads will try to access them at the same time, one thread will get a lock. Other thread will have to wait.
Non-static synchronized methods use some object as a lock. static synchronized methods use class.
Foo a = new Foo();
Foo b = new Foo();
a.syncMethod() and b.syncMethod() can run simultaneously, because they lock on different objects.
Foo.staticSyncMethod() and Foo.anotherStaticSyncMethod() cannot run simultaneously.
Assume you have two static methods and both are defined as synchronized. Both cannot execute concurrently as they share the same lock (which is the Class itself).
public static synchronized void Foo()
public static synchronized void Bar()
These two cannot run concurrently.
But they can execute concurrently with a non static synchronized method. The reason is non static synchronized methods lock on the actual instance that is running.
Good luck.
Related
I have a class as
public class ThreadExample extends Thread{
static int count = 0;
public static synchronized int increment(){
return count++;
}
public synchronized int decrement(){
return count--;
}
}
Here I have one static method and one non-static method.
First thread1 have called method increment() which is synchronized.It acquires lock on class level.
Here my question is if another thread2 is calling decrement() method will that thread2 will acquire lock on decrement() and how it works?
The synchronized keyword has two possible uses. It can be used as a modifier for methods, and it can be used as a statement. Besides, the synchronized modifier can be combined with static, and in that case the target object will be the enclosing class instead of the enclosing instance.
Scope | modifiers | corresponding statement
---------+---------------------+------------------------
static | synchronized static | synchronized (X.class)
instance | synchronized | synchronized (this)
If a method is static synchronized, the lock is acquired on the class object of the enclosing class, in your case on ThreadExample.class.
Although they're compiled into different byte code, the following two methods are equivalent:
public class Foo {
// static method with synchronized modifer
public static synchronized void foo1() {
// ...
}
// equivalent synchronized statement
public static void foo2() {
synchronized (Foo.class) {
// ...
}
}
}
If a method is synchronized (without static), the lock is acquired on the instance itself. Although they're compiled into different byte code, the following two methods are equivalent:
public class Foo {
// instance method with synchronized modifier
public synchronized void foo3() {
// ...
}
// equivalent synchronized statement
public void foo4() {
synchronized (this) {
// ...
}
}
}
So, increment() and decrement() are synchronized differently, and there can be a race condition.
Therefore, the variable count is not sufficiently protected from concurrent update.
++ and -- cannot be atomic themselves, as incrementing or decrementing a value requires a read-update-write cycle. Technically it could be atomic because some CPUs provide atomicity for that by providing corresponding instructions which will keep the bus / address obtained for themselves until the operation is performed. But the JVM does not rely on such things.
If you need a atomic int, you might want to look at java.util.concurrent.atomic.AtomicInteger.
How to do synchronized in C
synchronized is implemented with the VM environment methods MonitorEnter() and MonitorExit().
Pitfalls
When you use the synchronized modifier, you synchronize on something which is more or less public, i.e. visible to other objects and classes as well. The Monitor feature of java.lang.Object which provides the underlying facility for synchronized is public, as well as the native functions MonitorEnter() / MonitorExit() and the wait pool methods wait(), notify() and notifyAll(). This can lead to unexpected bugs and deadlocks if "somebody else" is also using "your object / your class" for synchronization.
Therefore it has become a pattern to actually not use the synchronized modifier but instead use synchronized statements on a private lock object, like this:
public class Foo {
private final Object lock = new Object();
public void foo() {
synchronized (lock) {
// ...
}
}
}
Now Foo can no longer be disturbed or blocked by somebody else synchronizing on it. You might think there might be a reasonable use case for that, but I think if you have a use case for locking across object / class boundaries, there's probably a big flaw in the design - things are not self-contained enough.
If you need a class lock instead of an instance lock, just make the variable static.
Note that when doing serialization, you will have to take care of the lock object. The simplest way is to actually not use Object, but this:
public class Lock implements Serializable {}
If you want to save serialization storage, you can declare the lock transient and recreate the lock during deserialization, but be careful about transient final, you need reflection or readResolve() for them, but that's a different story.
Calling synchronized static methods tries to acquire the lock of the class object. (ThreadExample in your case), while calling synchronized non-static methods tries to acquire the lock of the particular instance object. So essentially you are acquiring 2 different locks and thus your code is not thread-safe. The data count may be corrupted due to race condition
Oracle tutorial:
You might wonder what happens when a static synchronized method is
invoked, since a static method is associated with a class, not an
object. In this case, the thread acquires the intrinsic lock for the
Class object associated with the class. Thus access to class's static
fields is controlled by a lock that's distinct from the lock for any
instance of the class.
Static and instace level locks are two different locks and they are independant of each other.
Regarding scenario in question "First thread1 have called method increment() which is synchronized.It acquires lock on class level. Here my question is if another thread2 is calling decrement() method will that thread2 will acquire lock on decrement() and how it works"
even if thread1 is holding (class level)lock on increment method and thread2 calls decrement method it should aquire a (instance level)lock .
problem is not with aquiring the lock problem might start when they are trying to updated the shared variable.If two threads are trying to access count variable (one through static locking and other through instance level locking ) at a same time then there might be a RACE condition between two threads.
As suggested by Christian you can overcome this by using java.util.concurrent.atomic.AtomicInteger instead of int
For more details please visit URL
A static synchronized method and a non-static synchronized method will not block each other. The reason is static method locks on a Class instance while the non-static method locks on the this instance— both actions do not interfere with each other at all.
In your code one method is static synchronized and another method is just synchronized. Your code is not thread safe, even if two threads are executing two methods on same object, one thread (executing non-static method) acquires object level lock and proceed. Another thread executing static method acquires class level lock (i.e. ThreadExample.class ) and proceeds. Remember that static methods are always class level.
To make your code thread safe you need to have below changes in your example.
public static synchronized int decrement(){
return count--;
}
My question is related to thread safety of static variables.
Class A{
private static int test=0;
public static void synchronized m1(){
test=test+1;
}
public void synchronized m2(){
test=test+1;
}
}
If two threads, t1 having static lock and t2 having object lock, can
continue simultaneously, then how will state test of class A will be
thread safe?
May be , I am missing something very basic, but not sure how it works.
Based on below answers, I get the impression that if such states have
to be made thread safe, then either both locks should be held by a
thread which is updating this state, or make sure it is being accessed
by either only static methods or only non-static methods. right?
This is not thread safe. The methods use different monitor objects: the static method uses the class, and the instance method synchronizes using the object instance. You can make the instance method use the class as the monitor object by:
synchronized (A.class) {
...
if you need to. I'd consider making both methods static though, unless you need to access instance variables.
Its not thread-safe, and you (the question author) explained very well why.
If a class has only two synchronized methods (both either static or non static), the class is considered to be thread safe. What if one of the methods is static and one non static? Is it still thread safe, or bad things can happen if multiple threads call the methods?
There are some similar threads like static synchronized and non static synchronized methods in threads which describe the method calls are not blocking each other. But I am curious to know whether bad things in the world of thread safety (like inconsistent state, race condition, etc) can happen or not.
Edit 1:
Since static methods can't call non static methods, there should be no thread conflict from this side. On the other hand if a non static method calls the static one, it has to acquire the class lock. Which would be still thread safe. So by just having two methods (one static one none) I don't see any thread conflict. Is that right? In other words the only case I can see to have an issue is when the non static method accesses some static variables. But if all accesses are done through methods then I don't see any issues with thread safety. These were my thoughts. I am not sure whether I am missing something here since I am a little bit new to java concurrency.
In Java, the following:
public class MyClass
{
public synchronized void nonStaticMethod()
{
// code
}
public synchronized static void staticMethod()
{
// code
}
}
is equivalent to the following:
public class MyClass
{
public void nonStaticMethod()
{
synchronized(this)
{
// code
}
}
public void static staticMethod()
{
synchronized(MyClass.class)
{
// code
}
}
}
As you see, static methods use this as monitor object, and non-static methods use class object as monitor.
As this and MyClass.class are different objects, static and non-static methods may run concurrently.
To "fix" this, create a dedicated static monitor object and use it in both static and non-static methods:
public class MyClass
{
private static Object monitor = new Object();
public void nonStaticMethod()
{
synchronized(monitor)
{
// code
}
}
public static void staticMethod()
{
synchronized(monitor)
{
// code
}
}
}
What if one of the methods is static and one non static? Is it still thread safe, or bad things can happen if multiple threads call the methods?
Bad things can happen.
The static method will lock on the class monitor. The instance method will lock on the instance monitor. Since two different lock objects are in use, both methods could execute at the same time from different threads. If they share state (i.e. the instance method accesses static data) you will have problems.
What if one of the methods is static and one non static? Is it still thread safe, or bad things can happen if multiple threads call the methods?
Synchronization works with monitor (locks) that is taken on object.
In case of static method it's object of Class's class and in case of instance method it's this or calling object.
Since both the objects are different hence both synchronized static and non-static method will not block each other in case of multi-threading. Both the methods will execute simultaneously.
What if one of the methods is static and one non static
Yes.. Bad things can happen. Because if you synchronize on a static method, then you will be locking on the monitor of the Class object not on the class instancei.e, you will be locking on MyClass.class.
Whereas when you are synchronizing on an instance (non-static) method, you will actually be locking on the current instance i.e, this . So, you are locking on two different objects. So, the behaviour will be undefined and certainly not correct.
PS : In multi-threading, as a rule of thumb, please remember - If bad things can happen, they will happen.
What if ... Is it still thread safe?
Can't answer that question without a complete example. The question of thread safety is never a question about methods: It's a question about corruption of data structures and about liveness guarantees. Nobody can say whether a program is thread safe without knowing what all of the different threads do, what data they do it to, and how they coordinate (synchronize) with one another.
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.
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.