The point of this question is to illustrate that Java is not working as I expected.
How would you expect the following code to behave?
public class SynchTester {
private static SynchTester synchTester;
public synchronized static SynchTester getSynchTester(){
if(synchTester==null){
synchTester = new SynchTester();
}
return synchTester;
}
private SynchTester() {
SynchTester myTester = getSynchTester();
}
public static void main(String[] args) {
SynchTester tester = SynchTester.getSynchTester();
}
}
I would expect it to hang with a deadlock waiting on the recursion to complete, but instead it throws StackOverflow. Evidently synchronized does not block access to the same thread.
Is this a bug?
In Java, synchronized locks are reentrant.
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
Source: see bottom of this page
A synchronized method needs to be able to get a lock on the monitor object. The monitor object is the instance (or class for a static method). A thread that already has the lock does not need to get it again. So yes, that could cause a stackoverflow (harhar).
from the java tutorials:
When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
So I think the syncronized keyword worked as expected, and a synchronized recursive call is perfectly legal (and working) in java.
Related
package anonymous;
public class A {
public static int counter=0;
public static void main(String[] args) {
synchronized (args) {
//some logic
}
synchronized (args) {
//some logic
}
}
}
Let say one thread is executing in one synchronized block. Can another thread acquire lock on other synchronized block?
What will happen if a method call happened within a synchronized block to a nonsynchronized method? will that method be thread safe?
What if we try to access a static variable from a synchronized instance method?? At a time each thread accessing a synchronized block in each instance will try to modify the static variable. Is n't it? In this case how we can have thread safety??
Can another thread acquire lock on other synchronized block?
No, only one synchronized method at a time can run. A call to the other synchronized method will have to wait until the first method is done. This is described in the Java tutorials:
...it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
What will happen if a method call happened within a synchronized block to a nonsynchronized method? will that method be thread safe?
If the non-synchronized method is only called from synchronized methods belonging to this Object, then it can be considered thread-safe, since only one thread can execute one of the calling (synchronized) methods at a time.
Note that, as #Ordous points out below, static synchronized methods lock on the class, and non-static synchronized methods lock on the instance. Therefore a non-static method can interleave with a static method belonging to the class in question.
No, any other thread will not be able execute another block which acquires lock on the same object in your case args.
No. the other method which is being called from synchronized code block will not be thread safe. It can be called by any other thread from any other code block if it does not have synchronized keyword, because the thread need not to acquire any lock to execute that method.
This is common misunderstanding that synchronized keyword locks piece of code.
What synchronized keyword does?
It locks the object and not the method. So if you put synchronized keyword in front of a method then it will lock this object. so any other method with synchronized keyword can not be executed by any other thread.
This is not the same with static and not static method because when you have synchronized static method then the it will not lock this but it will lock default class object i.e A.class object. If you have another static sync method then that will not be executed by any other thread.
In case of sync blocks it will acquire lock on the object which is passed as argument in your case it is args.
so if there is another sync block anywhere else which acquires lock on the same object then it will have to wait until the first thread completes and releases the lock.
There is always a lock present on synchronised code. To access the code threads have to acquire the key , unlock , run and then handback the key.
There is a object level lock present , the lock is of the entire object and not of some method or block. So even if there are multiple synchronized block or methods on a single instance only one of the threads can acquire the key and access the synchronized code. It will then hand back the key to the object and then other threads can resume to acquire key and access synchronized code.
Incase you are wondering what happens to the static methods declared syncrhonized (since they have no objects/instances associated with them), in that case there is always also a lock present with the class itself. To access any synchronized static part of a class, a thread has to acquire the key from the class to unlock the lock.
Note:- the lock and key thing I mentioned is just to help understand, there is no methods or way to access keys or anything it is all internally maintained by JVM.
First and foremost, there can be multiple synchronized methods in a class. That is done by:
declaring the methods as synchronized
synchronized methods .
As per your question, if the threads are of the same class(multiple threads requesting the same resource, then no two objects of the same class can access a particular resource at the same time(concurrently). The thread that is holding the mutually exclusive lock(mutex) is in the monitor. All other such threads has to undergo waiting for the monitor.
Java Thread Scheduler ensures that any of the synchronized method might be required by the thread which is currently in the monitor, i.e. the one which is holding the lock. So, does not allow other threads to execute them concurrently.
That is not the case with non-synchronized methods, they can execute concurrently.
Can you tell me if following invocations are reentrant or not?
public class Foo {
public synchronized void doSomething() {}
public synchronized void doAnotherSomething() {}
}
public class Too {
private Foo foo;
public synchronized void doToo() {
foo.doSomething();
//...other thread interfere here....
foo.doAnotherSomething();
}
}
are 2 continuous invocations in method doToo() reentrant? I'm not sure about this case since foo.doSomething() method acquire and release the intrinsic lock, no nested synchronization between 2 invocations. Is there situation that other thread might interfere between 2 invocations?
First of all, regarding reentrant locks in Java:
Synchronized blocks in Java are reentrant. This means, that if a Java thread enters a
synchronized block of code, and thereby take the lock on the monitor object the block is synchronized on, the thread can enter other Java code blocks synchronized on the same monitor object.
Taken from here.
The two consecutive calls you described (in doToo) will not be interfered unless another object has a reference to Too's private Foo, since, to access foo, one needs to lock Too. However, the calls do not invoke reentry as the locks are acquired and released for every call. They would be reentrant if doSomething called doAnotherSomething or vice versa.
That depends entirely on what other threads are accessing. Can another thread take over the CPU between those functions? Yes. Will there be a race condition? Depends on many factors.
From what you posted foo.doSomething will be locked on foo, then released, then locked again upon entry to doAnotherSomething. So if another thread not locked on the same Too object tries to manipulate foo they will be able to do so between doSomething and doAnotherSomething. If everyone synchronized on the same Too object before manipulating the underlying foo object, then those two methods of foo will not have state manipulated between calls because the Too object method will block other threads until completion. Thus if you have a problem or not depends on your other accessors.
There is no reentrance here from what you posted, but java is ok with reentrant synchronization as Amir posted.
first of all locks are applicable on objects so need to create the object and then apply the lock.
are 2 continuous invocations in method doToo() reentrant? I
In your case they are not re-entrant . if code is something like below then they will be re-entrant .
public class Foo {
public synchronized void doSomething() {
doAnotherSomething();
}
public synchronized void doAnotherSomething() {}
}
Once lock has been acquired on one object then on same object it can traverse like in above case.
If I use synchronize(this) in two methods and one calls the other, will I get stuck in a deadlock situation or will it work because the thread already owns the lock?
Picture the class below:
public class Test {
public void foo() {
synchronize(this) {
bar();
}
}
public void bar() {
synchronize(this) {
// do something
}
}
}
As you can see, there are two methods foo and bar, which both rely on synchronization.
When calling foo(), a lock will be obtained on (this); will bar try to do the same when called by foo (and thus causing a deadlock) or will it realize that the lock has already been obtained by the same thread?
Hope my explanation is more or less clear ;-)
The synchronized block is reentrant (in fact, Java monitors are reentrant, to be perfectly clear), thus no deadlock can happen in your situation.
According to the docs:
Recall that a thread cannot acquire a lock owned by another thread.
But a thread can acquire a lock that it already owns.
If thread holds lock of object it can enter to other synchronized blocks based on that lock object.
Here you can read that
"...thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block."
One thing to be careful of though is if:
Thread A has the lock in foo() and needs to call bar()
and Thread B has the lock in bar() while needing to call foo()
I have two methods in a java class that both have a block of code that synchronize using the same object. I understand that in the JAVA synchronization scheme locks acquired by a thread are reentrant. With this can i safely say the below piece of code will not cause any issues in all cases?
public class Someclass
{
private static final Object LCK_OBJ = new Object();
//.....
publc void method1()
{
//some code....
synchronized(LCK_OBJ)
{
//some sychronized code.
method2(..);
}
//some more code....
}
protected static final void method2(..)
{
Someclass ref = null;
//some code which gets different other references of SomeClass in a loop....
ref.method3(..);
}
publc void method3()
{
//some code....
synchronized(LCK_OBJ)
{
//some sychronized code.
}
//some more code....
}
}//end of class
Yes, synchronized blocks are reentrant. ReentrantLock is also reentrant and if you want to code the blocks yourself, you might want to use that instead as it has more flexibiliy/functionality.
I would make sure any lock is final If a lock object cannot be final, it is almost certainly a bug (or a source of confusion)
For comparison purposes, not all locks in Java are reentrant. FileLock is not as it passes the request directly to the OS.
Yes you can, but this code won't compile: you are calling an instance method "method3" from a static method "method2". Other than that: if a thread has managed to aquire a lock in "method1" if will still have the lock in "method3".
Yes, the same thread can enter a synchronized block on the same lock multiple times. Be careful not to acquire other locks in a different order, otherwise you can cause a deadlock.
Though this code wont compile as already mentioned , lets consider the case that method2 is not static.A call from method1 to method2 and then to method3 is good example of reentrant synchronization.When a thread initiates, it creates a new stack with the run() at the bottom of the stack.Since the call to method1 comes from run() it is added in the stack above run() and then goes the method2 and method3 in the stack. Also, as the object lock is taken by method2 on the stack , the lock is maintained on all synchronized api called .The release of the lock is initiated by unwrapping the top most method (method3 in this case)in the stack till the actual api is reached which calls synchronize.
This question already has answers here:
Is there an advantage to use a Synchronized Method instead of a Synchronized Block?
(23 answers)
Closed 5 years ago.
What is the difference between a synchronized method and synchronized block in Java ?
I have been searching the answer on the Net, people seem to be so unsure about this one :-(
My take would be there is no difference between the two, except that the synch block might be more localized in scope and hence the lock will be of lesser time ??
And in case of Lock on a static method, on what is the Lock taken ? What is the meaning of a Lock on Class ?
A synchronized method uses the method receiver as a lock (i.e. this for non static methods, and the enclosing class for static methods). Synchronized blocks uses the expression as a lock.
So the following two methods are equivalent from locking prospective:
synchronized void mymethod() { ... }
void mymethod() {
synchronized (this) { ... }
}
For static methods, the class will be locked:
class MyClass {
synchronized static mystatic() { ... }
static mystaticeq() {
syncrhonized (MyClass.class) { ... }
}
}
For synchronized blocks, you can use any non-null object as a lock:
synchronized (mymap) {
mymap.put(..., ...);
}
Lock scope
For synchronized methods, the lock will be held throughout the method scope, while in the synchronized block, the lock is held only during that block scope (otherwise known as critical section). In practice, the JVM is permitted to optimize by removing some operations out of the synchronized block execution if it can prove that it can be done safely.
A synchronized method is shorthand. This:
class Something {
public synchronized void doSomething() {
...
}
public static synchronized void doSomethingStatic() {
...
}
}
is, for all intents and purposes, equivalent to this:
class Something {
public void doSomething() {
synchronized(this) {
...
}
}
public static void doSomethingStatic() {
synchronized(Something.class) {
...
}
}
}
(Where Something.class is the class object for the class Something.)
So indeed, with a synchronized block, you can be more specific about your lock, and more fine-grained about when you want to use it, but other than that there's no difference.
Yes, that is one difference. The other is that you can acquire a lock on other objects than this.
The key difference is this: if you declare a method to be synchronized, then the entire body of the method becomes synchronized; if you use the synchronized block, however, then you can surround just the "critical section" of the method in the synchronized block, while leaving the rest of the method out of the block.
If the entire method is part of the critical section, then there effectively is no difference. If that is not the case, then you should use a synchronized block around just the critical section. The more statements you have in a synchronized block, the less overall parallelism you get, so you want to keep those to the minimum.
A synchronized method locks on the object instance the method is contained in.
Where as a synchronized block can lock on ANY object - typically a mutex obect defined as an instance variable. This allows more control over what locks are in operation.
My take would be there is no difference between the two, except that the synch block might be more localized in scope and hence the lock will be of lesser time ??
Yes. You are right. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock.
Example from java tutorial:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
Synchronized statements are also useful for improving concurrency with fine-grained synchronization. You can find good example on same tutorial page for below use case.
Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.
And in case of Lock on a static method, on what is the Lock taken ? What is the meaning of a Lock on Class ?
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.
When you make a method as synchronized ( non static ) :
It is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
If you make a method as static synchronized :
It is not possible for two invocations of static synchronized methods on different objects of same class to interleave. When one thread is executing a static synchronized method for an object of Class A, all other threads that invoke static synchronized methods on any of objects of Class A block (suspend execution) until the first thread is done with the method execution.
You find better alternatives to synchronization in this SE question:
Avoid synchronized(this) in Java?