I understand that Java instance synchronized methods can run parallel and the static ones will serialize the methods; my lack of understanding is, since the static method locks the Class object, what happens with other Class objects; are we locking between all static classes?
thanks.
Instead of taking the lock on the instance/object you are taking it on the class it self.
When you lock the class you are only locking that class, not all classes.
From the docs
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.
Java classes have a monitor associated with the class instance. Since there is only one class instance per class the lock will only be acquired on that class instance.
Now each class defined has its own instance and thus its own monitor, so to answer your question: Synchronizing a static method will only block access to that class.
Related
One common (1,2) way of implementing a singleton uses an inner class with a static member:
public class Singleton {
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
private Singleton() {
//...
}
}
This implementation is said to be lazily initialized and thread-safe. But what exactly guarantees its thread safety? JLS 17 that deals with Threads and Locks doesn't mention that static fields have any sort of happens-before relationship. How can I be sure that the initialization will only happen once and that all threads see the same instance?
It's well described in Java Concurrency in Practice:
The lazy initialization holder class idiom uses a class whose only purpose is to initialize the Resource. The JVM defers initializing the ResourceHolder class until it is
actually used [JLS 12.4.1], and because the Resource is initialized
with a static initializer, no additional synchronization is needed.
The first call to getresource by any thread causes ResourceHolder to
be loaded and initialized, at which time the initialization of the
Resource happens through the static initializer.
Static initialization
Static initializers are run by the JVM at class initialization time,
after class loading but before the class is used by any thread.
Because the JVM acquires a lock during initialization [JLS 12.4.2] and
this lock is acquired by each thread at least once to ensure that the
class has been loaded, memory writes made during static initialization
are automatically visible to all threads. Thus statically initialized
objects require no explicit synchronization either during construction
or when being referenced.
There are two points we need to understand first:
Static initialization happens only once when loading the class
Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory
....
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class
This means that static initializers executed only once when initializing the object class (the actual Class object , not an instance of the class).
Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time.
For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation.
Now, in simple words, when two threads try to initialize instance the first thread which acquire LC is the one that actually initialize instnace, and because it does that statically, java provides a promise that it happens only once.
For more information regarding initialization lock read JSL 17
something about static:
instances of class share static method
the similar questions:
Java: when to use static methods
What does the 'static' keyword do in a class?
I am confusing about:
static method just have only one memory block?
if i use static method in multithreading, will it block?
I am confusing about:
static method just have only one memory block? if i use static method
in multithreading, will it block?
The static keyword in Java simply means "without regard or knowledge of any particular instance of an object."
An instance method can use this to access the fields of its associated instance, but a static method has no associated instance and so this makes no sense.
In multithreading, thread safety involves protecting the consistency and integrity of mutable data. Because objects encapsulate the state of their instance fields, instance methods only need to be concerned about thread safety in those circumstances in which more than one thread will be accessing the same object.
So while thread confinement of an object is a valid thread safety policy for instances of a class, this same reasoning is invalid for static methods because they have no instance.
This has nothing to do with memory blocks at all. It just has to do with access. An object instance is accessed through a reference. If the reference is thread confined, then the object to which that reference points will always be thread safe. But any thread anywhere that can access your class can potentially get to its static members because no reference to an instance is needed to use them.
Static methods are non-blocking by default. You can implement your own synchronization/thread safety policy and have your static method block if you wish.
Each thread has its own stack space, each time a thread calls a method (static or virtual) that call allocates a stack frame, which holds local variables. nothing about this is specific to static methods.
Static methods can be called concurrently by multiple threads, unless you specifically do something to thwart that, such as requiring that the caller acquire a lock (such as using the synchronized keyword).
Static methods are good for cases where there is no shared state. They may be ok in cases accessing or modifying threadsafe shared state, depending on what level of concurrency is needed and how efficient the threadsafe things being accessed are.
Look out for bottlenecks. Putting the synchronized keyword on a static method may be a problem as that limits your application to calling it with only one thread at a time. Alternative strategies including using atomic objects, using threadsafe data structures designed for high concurrency, or using thread confinement may be preferable to locking.
static method just have only one memory block?
No, methods don't have memory blocks. Threads executing those methods do. Each thread will have it's own memory on the stack where it stores all the method arguments and variables.
if i use static method in multithreading, will it block
A thread cannot access the memory of another thread, but if there is some resource that belongs to all instances and is supposed to be accessed sequentially, then you can synchronize or lock the static method, thus making it a blocking one. Otherwise, no.
Even though there is one instance of a static method, each thread gets its own stack-frame, which means each thread can exercise the same method but in a separate "world" from other threads.
Threads always get their own stack, even for a singleton class (one instance):
so, when to use static methods and when to not?
The main reason for not using static methods everywhere is that they are difficult to unit-test barring manipulating compiled code (Powermock), so static methods should have no dependencies that would require mocking, i.e. the test calls the real method with an input and asserts the output, verbatim, in two steps.
Non-static methods allow you to isolate your test solely to that method by stubbing, mocking, or spying on objects that the method depends on.
Background:
I'm reading Java Concurrency in Practice, and Listing 2.7 has the following code. The example states that this code only functions because monitor locks are re-entrant.
I would have originally thought that when you called super.doSomething() then it would have acquired a lock on the base class object and not the derived class object. That would mean this situation would not require re-entrancy. Having said this, I also understand that both base class and derived class methods can alter base class fields, so the lock they use must be common (meaning I was obviously mistaken).
Question:
Is there one "intrinsic" lock per object in an inheritance hierarchy, or one "intrinsic" lock associated with the most derived object (or least derived object) in the hierarchy only?
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling doSomething");
super.doSomething();
}
}
I would have originally thought that when you called super.doSomething() then it would have acquired a lock on the base class object and not the derived class object.
There's only one object - if you create an instance of LoggingWidget, there's only one object created, with all the fields from LoggingWidget and also all the fields from Widget. It's not like it creates an instance of LoggingWidget that refers to an instance of Widget.
There's only one object, and therefore only one lock, wherever you synchronize on it.
As per my knowledge in Java class with
Non static synchronize method : lock acquire on particular object
Static synchronize method : lock acquire on class
I am little bit confuse with this, since we can call the static method by class name OR by object name.
Please assume there are 4 methods is my class all are synchronized. 2 methods are static and 2 are not static. If I create 1 object of my class "obj1" and there are 2 threads Thread1 and Thread2 as well
Question 1: if I will try to access the static synchronized method, using the obj1 (or class name), does it mean there is no lock on "obj1", only 2 static methods will be locked (class level lock)? Does this mean another thread can access non-static method, but not the static method using the "obj1" simultaneously?
Question 2: if I will try to access the non-static synchronized method using the obj1 in Thread1, does it mean only 2 methods are locked for Thread2? Does this mean Thread2 can access 2 static methods, OR we can access the static method using the className(MyClass) as well simultaneously?
Question 3: if all the methods in my class are static and synchronized, does it mean there will be no object level lock and there is only one class level lock for all threads?
Please explain little bit about the class level lock.
Even if you call a static method with
someObject.staticMethod()
It doesn't change the fact that the lock is on the Class object. It just means that you're calling static methods in a confusing way and you should call it properly. Just because it works perfectly well, doesn't mean it should be used (unless you intend to make your code less readable).
There's nothing special about the class level lock. It just uses the Class object instead of the instance, and since all static synchronization uses the same Class object, it works like it does.
As for your last question, yes. If you have only static synchronized methods, they will all share the Class object as their lock, no matter how many instances of the class you have created.
I'm creating a static class which is going to hold some vectors with info.
I have to make it synchronized so that the class will be locked if someone is editing or reading from the vectors.
What is the best way to do this?
Is it enough to have a function which is synchronized inside the class like this:
public synchronized insertIntoVector(int id)
{
}
Thanks in advance :)
Firstly, you need to define exactly what you mean by "static class". At first, I thought you meant a class where all methods were static (that wasn't meant to be instantiated) - but your code snippet implies this isn't the case.
In any case, synchronized methods inside the class are equivalent to synchronized(this) if they are instance methods, or synchronized(TheContainingClassName.class) if they're static methods.
If you are either creating a non-instantiable class with all static methods, or if you are creating a class that will act as a singleton, then synchronizing every method of the class will ensure that only one thread can be calling methods at once.
Do try to ensure that your methods are atomic though, if possible; calls to different methods can be interleaved by other threads, so something like a getFoo() call followed by a setFoo() (perhaps after incrementing the foo variable) may not have the desired effect if another thread called setFoo() inbetween. The best approach would be to have a method such as incrementFoo(); alternatively (if this is not possible) you can publish the synchronization details so that your callers can manually hold a lock over the class/instance during the entire sequence of calls.
AFAIK, there's no such thing as "static class" in Java. Do you mean a class that contains only static methods? If so, then
public static synchronized void insertIntoVector(int id) {
}
synchronizes with respect to the class object, which is sufficient, if there are only static methods and all of them are synchronized.
If you mean static inner class (where the word "static" has a different meaning than in static methods), then
public synchronized void insertIntoVector(int id)
{
}
synchronizes with respect to an instance of that static inner class.