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.
Related
Assuming I have two different objects of same class, do they will able to execute the same synchronized method at the same time because the lock is on the object ant not on the method.
Example:
MyCLass cc= new MyCLass();
MyCLass cc1= new MyCLass();
Now create two thread
t1 --- it will call cc.meth
t2--it will call cc1.meth
// in this case t1 thread get lock on object cc and t2 thread get lock on object cc1.. it will work
synchronized meth(){
}
is it correct?
I think your question is answered here https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html, that tell that just one instance of the same class is locked while executing a synchronized method, obviously even if executed by a thread.
You are right. Synchronized methods lock their instance, not the class nor the method (for synchronized static methods, see below...).
So, on a given instance, only one thread can be inside any of its synchronized methods, but that does not block threads working with other instances of the same class.
Synchronized static methods lock the class (they don't have a this instance), so of all threads only one at a time can be executing inside a synchronized static method of the given class.
And if you need some other locking scheme, you can use a synchronized(someObject) { ... } block, which synchronizes on someObject, and then you are free to select the object that represents the mutual-exclusion group.
So, a synchronized method A.b() is equivalent to synchronized(this) {...} or (in the static case) synchronized(A.class) {...}.
synchronized implemented by monitorenter. You can see it in your byte code. monitorenter use the object monitor - the monitor of the instance of the class (not the class itself). So it is the expected behavior. If two threads try to execute synchronized methods of two different instances at the same time, both should not be blocked.
Actually it is better to avoid synchronized if the objects are not shared because synchronized is not good for performance. You should start thinking about synchronized only when you know that the object will be shared by more than one thread, which is not your case.
EDIT:
More simple explanation is that this code:
public synchronized void meth() {
...
}
equivalent to:
public void meth() {
synchronized (this){
...
}
}
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.
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 a synchronized method calls another synchronized method, is it thread safe?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Yes, when you mark methods as synchronized, then you are really doing this:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
When the thread call gets into method2 from method1, then it will ensure that it holds the lock to this, which it already has, and thus it can pass through.
Now when another thread tries to get directly into method1 or method2, then it will block until it can get the lock (this), and only then it will enter into any of the two methods.
As noted by James Black in the comments, you do have to be aware with what you do inside of the method body.
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
Suddenly it's not thread safe because you are looking at a ConcurrentModificationException in your future because method3 is unsynchronized, and thus could be called by Thread A while Thread B is working in method1.
Is a method marked with synchronized call another synchronized method thread safe.
In general, it is not possible to say. It depends on what the methods do, and what other methods on the same and other classes do.
However, we can be sure that calls to method1 and method2 on the same object made by different threads will not execute simultaneously. Depending on what the methods do, this may be sufficient to say that the class is thread-safe with respect to these methods.
From the Java Tutorials site http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
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.
when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads
So Java will ensure that if 2 threads are executing the same method, the methods will not executed consurrently but one after another.
But you need to be aware of the Liveness problem, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
And also whether you are locking uncessarily, cause in the code you used this, which locks the whole object, if your object only needs sync access to one variable you should just lock that variable.
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?